where clause for tuple structs recommended at wrong place causing syntax errors · Issue #91520 · rust-lang/rust (original) (raw)

Me Newbie. I had this issue while trying to create a new type to abstract over a HashMap, went to rust discord where i got the fix. then, as i got the suggestion as a quickfix from vscode, i thought it was a Rust analyzer bug, rust-lang/rust-analyzer#10923 . but this is a rust bug it seems.

Reproduce error:

  1. add derive_more and halfbrown as dependencies. //hashbrown will probably work too
  2. create a tuple struct with halfbrown::HashMap as its only field. UOMap<K,V>(halfbrown::HashMap<K,V>)
  3. derive IntoIterator using derive_more with the #[derive(IntoIterator)] and vscode gives this error.
    into

cargo check output:

error[E0277]: the trait bound `halfbrown::HashMap<K, V>: IntoIterator` is not satisfied
   --> src/main.rs:7:10
    |
7   | #[derive(IntoIterator)]
    |          ^^^^^^^^^^^^ the trait `IntoIterator` is not implemented for `halfbrown::HashMap<K, V>`
    |
note: required by a bound in `IntoIterator`
   --> /home/red/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/collect.rs:204:1
    |
204 | / pub trait IntoIterator {
205 | |     /// The type of the elements being iterated over.
206 | |     #[stable(feature = "rust1", since = "1.0.0")]
207 | |     type Item;
...   |
234 | |     fn into_iter(self) -> Self::IntoIter;
235 | | }
    | |_^ required by this bound in `IntoIterator`
    = note: this error originates in the derive macro `IntoIterator` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
    |
8   | pub struct UOMap<K: std::hash::Hash,V> where halfbrown::HashMap<K, V>: IntoIterator(HashMap<K, V>);
    |                                        ++++++++++++++++++++++++++++++++++++++++++++

error[E0277]: the trait bound `halfbrown::HashMap<K, V>: IntoIterator` is not satisfied
 --> src/main.rs:7:10
  |
7 | #[derive(IntoIterator)]
  |          ^^^^^^^^^^^^ the trait `IntoIterator` is not implemented for `halfbrown::HashMap<K, V>`
  |
  = note: this error originates in the derive macro `IntoIterator` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider introducing a `where` bound, but there might be an alternative better way to express this requirement
  |
8 | pub struct UOMap<K: std::hash::Hash,V> where halfbrown::HashMap<K, V>: IntoIterator(HashMap<K, V>);
  |                                        ++++++++++++++++++++++++++++++++++++++++++++

For more information about this error, try `rustc --explain E0277`.
  1. the suggestion 8 | pub struct UOMap<K: std::hash::Hash,V> where halfbrown::HashMap<K, V>: IntoIterator(HashMap<K, V>); with where clause between the struct name and the parenthesis which declare the fields, is wrong and introduces a whole new class of errors
    after
    cargo output:
error: proc-macro derive panicked
 --> src/main.rs:7:10
  |
7 | #[derive(IntoIterator)]
  |          ^^^^^^^^^^^^
  |
  = help: message: derive(IntoIterator) only works when forwarding to a single field. Try putting #[into_iterator] or #[into_iterator(ignore)] on the fields in the struct

error[E0658]: parenthetical notation is only stable when used with `Fn`-family traits
 --> src/main.rs:8:72
  |
8 | pub struct UOMap<K: std::hash::Hash,V> where halfbrown::HashMap<K, V>: std::iter::IntoIterator(HashMap<K, V>);
  |                                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information

error[E0107]: this trait takes 0 generic arguments but 1 generic argument was supplied
   --> src/main.rs:8:83
    |
8   | pub struct UOMap<K: std::hash::Hash,V> where halfbrown::HashMap<K, V>: std::iter::IntoIterator(HashMap<K, V>);
    |                                                                                   ^^^^^^^^^^^^--------------- help: remove these parenthetical generics
    |                                                                                   |
    |                                                                                   expected 0 generic arguments
    |
note: trait defined here, with 0 generic parameters
   --> /home/red/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/collect.rs:204:11
    |
204 | pub trait IntoIterator {
    |           ^^^^^^^^^^^^

error[E0220]: associated type `Output` not found for `IntoIterator`
 --> src/main.rs:8:83
  |
8 | pub struct UOMap<K: std::hash::Hash,V> where halfbrown::HashMap<K, V>: std::iter::IntoIterator(HashMap<K, V>);
  |                                                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated type `Output` not found

Some errors have detailed explanations: E0107, E0220, E0658.
For more information about an error, try `rustc --explain E0107`.

The Fix:
changing
pub struct UOMap<K: std::hash::Hash,V> where halfbrown::HashMap<K, V>: std::iter::IntoIterator(HashMap<K, V>);
to
pub struct UOMap<K: std::hash::Hash,V>(HashMap<K, V>) where halfbrown::HashMap<K, V>: std::iter::IntoIterator;
basically, insert the where clause AFTER the closing parenthesis.
from what i was told on the discord, where clause needs to come just before the first {, but idk how it will be dealt with in regards to tuple struct.

rustc version: rustc 1.57.0 (f1edd04 2021-11-29)