Clippy wants me to use an unstable feature

Clippy complains about this:

impl <I: 'static+Eq+Hash+Send+Clone, P: 'static+Ord+Send+Clone>PriorityChannel<I,P> {    
    pub fn init(early_quit: bool) -> (Sender<(I,P)>, Receiver<(I,P)>) {

On the "pub fn init" line, Clippy complains:

warning: very complex type used. Consider factoring parts into type definitions

But if I try to fix that, with

type ChannelCombo = (Sender<(I,P)>, Receiver<(I,P)>);

the compiler tells me:

Error[E0658]: inherent associated types are unstable
  --> src/assets/priority_channel.rs:30:5
   |
30 |     type ChannelCombo = (Sender<(I,P)>, Receiver<(I,P)>);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information

In that issue, from 2013, someone was trying to do what I did here - name a complex type in a generic. That feature isn't in stable yet.

Am I doing this wrong, or is that check in Clippy premature?

The intended suggestion is that you should put the type alias at the top level, not inside the impl block.

pub type ChannelCombo<I, P> = (Sender<(I, P)>, Receiver<(I, P)>);

impl<I: 'static + Eq + Hash + Send + Clone, P: 'static + Ord + Send + Clone> PriorityChannel<I, P> {
    pub fn init(early_quit: bool) -> ChannelCombo<I, P> {
        // ...
    }
}

(I don't necessarily agree with this suggestion—Clippy can be kind of hit-or-miss—but it's not incorrect.)

1 Like

You could have a global type alias of

type SndRcv<T> = (Sender<T>, Receiver<T>);

and then use

pub fn init(early_quit: bool) -> SndRcv<(I,P)>

as your function header. Potentially more even more usefully, depending on convention and how it's intended to be used, you could even use a named type:

pub struct ChanPair<T> {
    pub snd: Sender<T>,
    pub rcv: Receiver<T>,
}

and then use sites could look like

let ChanPair { snd, rcv } = PriorityChannel::init(false);

The complex type lint is ime the most likely "tunable threshold" lint to hit. Certain projects that use a lot of generics (think nalgebra, diesel) naturally have a higher tolerance for complex types.

Given that (Sender<T>, Receiver<T>) is a common idiom, established by std and used by popular ecosystem crates, this example is right on the line, and I think I'd opt to allow the clippy lint in this case, to match reader expectation (who expect to see (Sender<_>, Receiver<_>) in documentation, not e.g. SndRcv<_>, even though the latter removes the potential of the types not matching).

3 Likes

Ah. The type alias does not need to be visible at the outer scope, but that does work, and makes Clippy happy.

I think this makes the code less clear, but so be it. Clippy doesn't recognize the symmetry in

(Sender<(I,P)>, Receiver<(I,P)>)

as reducing the perceived complexity. No doubt the ML people could come up with a human-oriented complexity metric, but that's for the future.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.