This function depends on never type fallback being `()`

What does this mean and how can I fix this warning?

warning: this function depends on never type fallback being `()`
  --> src/service/redis_service.rs:31:5
   |
31 |     pub async fn set_str<V: AsRef<[u8]>>(&self, key: &str, value: V) -> Result<(), RedisErr> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #123748 <https://github.com/rust-lang/rust/issues/123748>
   = help: specify the types explicitly
note: in edition 2024, the requirement `!: FromRedisValue` will fail
  --> src/service/redis_service.rs:39:41
   |
39 |         let _ = &mut Self::init().await.set(key, &encoded)?;
   |                                         ^^^
   = note: `#[warn(dependency_on_unit_never_type_fallback)]` on by default

I figured out that I can fix this by adding let _: &mut () = &mut Self::init().await.set(key, &encoded)?; but this is way more confusing than before.

Can you please post the offending code example. Its hard to help you solely based on the error message.

Sure.

pub async fn set_str<V: AsRef<[u8]>>(&self, key: &str, value: V) -> Result<(), RedisErr> {

        info!("Hash new value...");

        let encoded: String = encode(&value);

        info!("Write into redis cache: {}, {}", &key, &encoded);

        let _: &mut () = &mut Self::init().await.set(key, &encoded)?;
        
        let expire = 16*16*27*25*7; // Registration URLs expire after 2 weeks
        
        if key.eq("uuids") {
            let _: &mut () = &mut Self::init().await.expire(String::from("uuids"), expire)?;
        }

        Ok(())
    }

What is the signature (fn ... {) of the set() method you are calling?

This redis::Commands::set()

Ah so the return type is set by the type parameter RV: FromRedisValue and isn't otherwise constrained. I can reproduce the error in this self-contained program:

trait ReturnTrait {
    fn value() -> Self;
}
struct Error;
impl ReturnTrait for () {
    fn value() -> Self {}
}
// ensure we’re not using the only-one-trait-impl inference rule
impl ReturnTrait for bool {
    fn value() -> Self { false }
}

fn set<R: ReturnTrait>() -> Result<R, Error> {
    Ok(R::value())
}

async fn usage() -> Result<(), Error> {
    let _ = &mut set()?;
    Ok(())
}

The part of the warning that says that this will fail in 2024 seems to be correct. I’m not sure why ! is involved — ah, apparently something about the ? operator gets it involved: this function depends on never type fallback being `()` · Issue #126466 · rust-lang/rust · GitHub

As to your actual question, here is how to properly and concisely constrain the return type to ():

let () = Self::init().await.set(key, &encoded)?;

It can also be written as:

() = Self::init().await.set(key, &encoded)?;

but I personally don’t care for that (it’s technically an assignment to a tuple of zero variables). In either case, the &mut was doing you no good but adding verbosity.

4 Likes

Another solution would be to just specify the generic type argument:

Self::init().await.set::<_, _, ()>(key, &encoded)?;
1 Like

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.