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

Type checker gives confusing tip when collecting std::str::Char into std::rc::Rc using std::from::From. #70959

Closed
hank-der-hafenarbeiter opened this issue Apr 9, 2020 · 2 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. D-confusing Diagnostics: Confusing error or lint that should be reworked. D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@hank-der-hafenarbeiter
Copy link
Contributor

hank-der-hafenarbeiter commented Apr 9, 2020

Hey everyone,

I noticed that when collecting an std::str::Chars into a std::rc::Rc using Rc::from(...), the compiler tells you to annotate the type on your variable, when you actually need to annotate the type of your std::Iter::collect() call.

This code produces the bug:

fn main() {
    let s = "Hello, Github!!!!".to_string();
    let r:Rc<str> = Rc::from(s.chars().collect());
}

The compiler tells me to annotate the type of r, which already has a type annotation.

error[E0283]: type annotations needed for `std::rc::Rc<str>`
 --> src/main.rs:5:21
  |
5 |     let r:Rc<str> = Rc::from(s.chars().collect());
  |         -           ^^^^^^^^ cannot infer type for struct `std::rc::Rc<str>`
  |         |
  |         consider giving `r` a type
  |
  = note: cannot resolve `std::rc::Rc<str>: std::convert::From<_>`
  = note: required by `std::convert::From::from`

In actuality the fix is to annotate the collect()-call:

fn main() {
    let s = "Hello, Github!!!!".to_string();
    let r:Rc<str> = Rc::from(s.chars().collect::<String>());
}

Meta

I used the following version:

rustc --version --verbose:

rustc 1.44.0-nightly (1edd389cc 2020-03-23)
binary: rustc
commit-hash: 1edd389cc4c7b5be7a3dd4fe4b986f6017018e54
commit-date: 2020-03-23
host: x86_64-unknown-linux-gnu
release: 1.44.0-nightly
LLVM version: 9.0

The current beta (1.43.0-beta.5) and stable (1.42.0) on the rust playground produce the same output.

@hank-der-hafenarbeiter hank-der-hafenarbeiter added the C-bug Category: This is a bug. label Apr 9, 2020
@jonas-schievink jonas-schievink added A-diagnostics Area: Messages for errors, warnings, and lints D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 9, 2020
@estebank estebank added the D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. label Apr 9, 2020
@hank-der-hafenarbeiter
Copy link
Contributor Author

hank-der-hafenarbeiter commented Apr 11, 2020

Small update:

Replacing let r:Rc<str> = Rc::from(s.chars().collect()); with let r:Rc<str> = s.chars().collect().into();
gives a meaningful error:

error[E0282]: type annotations needed
 --> src/main.rs:5:31
  |
5 |     let r:Rc<str> = s.chars().collect().into();
  |                               ^^^^^^^
  |                               |
  |                               cannot infer type for type parameter `B` declared on the method `collect`
  |                               help: consider specifying the type argument in the method call: `collect::<B>`
  |
  = note: type must be known at this point


@estebank
Copy link
Contributor

Current output:

error[E0283]: type annotations needed
 --> f71.rs:4:40
  |
4 |     let r:Rc<str> = Rc::from(s.chars().collect());
  |                     --------           ^^^^^^^ cannot infer type of the type parameter `B` declared on the method `collect`
  |                     |
  |                     required by a bound introduced by this call
  |
  = note: multiple `impl`s satisfying `Rc<str>: From<_>` found in the following crates: `alloc`, `core`:
          - impl From<String> for Rc<str>;
          - impl<'a, B> From<Cow<'a, B>> for Rc<B>
            where B: ToOwned, Rc<B>: From<&'a B>, Rc<B>: From<<B as ToOwned>::Owned>, B: ?Sized;
          - impl<> From<&str> for Rc<str>;
          - impl<T, A> From<Box<T, A>> for Rc<T, A>
            where A: Allocator, T: ?Sized;
          - impl<T> From<!> for T;
          - impl<T> From<T> for T;
help: consider specifying the generic argument
  |
4 |     let r:Rc<str> = Rc::from(s.chars().collect::<Vec<_>>());
  |                                               ++++++++++

After #114811:

error[E0283]: type annotations needed
    --> f71.rs:4:40
     |
4    |     let r:Rc<str> = Rc::from(s.chars().collect());
     |                                        ^^^^^^^ cannot infer type of the type parameter `B` declared on the method `collect`
     |
     = note: multiple `impl`s satisfying `_: FromIterator<char>` found in the following crates: `alloc`, `hashbrown`, `std`:
             - impl FromIterator<char> for String;
             - impl<'a, T> FromIterator<T> for Cow<'a, [T]>
               where T: Clone;
             - impl<'a> FromIterator<char> for Cow<'a, str>;
             - impl<I> FromIterator<I> for Box<[I]>;
             - impl<T, S, A> FromIterator<T> for hashbrown::set::HashSet<T, S, A>
               where T: Eq, T: Hash, S: BuildHasher, S: Default, A: Default, A: Allocator, A: Clone;
             - impl<T, S> FromIterator<T> for HashSet<T, S>
               where T: Eq, T: Hash, S: BuildHasher, S: Default;
             - impl<T> FromIterator<T> for Arc<[T]>;
             - impl<T> FromIterator<T> for BTreeSet<T>
               where T: Ord;
             - impl<T> FromIterator<T> for BinaryHeap<T>
               where T: Ord;
             - impl<T> FromIterator<T> for LinkedList<T>;
             - impl<T> FromIterator<T> for Rc<[T]>;
             - impl<T> FromIterator<T> for Vec<T>;
             - impl<T> FromIterator<T> for VecDeque<T>;
note: required by a bound in `collect`
    --> /home/gh-estebank/rust/library/core/src/iter/traits/iterator.rs:2049:19
     |
2049 |     fn collect<B: FromIterator<Self::Item>>(self) -> B
     |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Iterator::collect`
help: consider specifying the generic argument
     |
4    |     let r:Rc<str> = Rc::from(s.chars().collect::<Vec<_>>());
     |                                               ++++++++++

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-bug Category: This is a bug. D-confusing Diagnostics: Confusing error or lint that should be reworked. D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants