patrickn
patrickn

Reputation: 2561

"cannot infer type for `T`" when using error enum variants

I've got the following snippet:

 pub fn init(&mut self, opts: InitOptions) -> Result<(), PostalError> {
    let _ = self.mutex.lock();
    unsafe {
        if !libpostal_setup() {
            Err(PostalError::LibpostalSetup);
        }
    }
    self.setup_done = true;
    if opts.expand_address {
        unsafe {
            if !libpostal_setup_language_classifier() {
                Err(PostalError::LibpostalEnableExpansion);
            }
        }
        self.expand_address_enabled = true;
    }
    Ok(())
}

which yields this error when compiling:

error[E0282]: type annotations needed
--> src/lib.rs:110:17
 |
 110 |             Err(PostalError::LibpostalSetup);
 |                 ^^^ cannot infer type for `T`

I've tried a number of things:

  1. Adding type annotations to Err, as suggested; e.g. Err::<(), PostalError>(PostalError::LibpostalSetup);, which compiles but produces warnings and incorrect runtime behavior (i.e. a single unwrap() no longer works on the returned Result).

  2. Changing from the unit type () to u8 (for testing).

  3. Fiddling with enum variant signature changes in general in a variety of ways, to no avail.

What is curious is that I have another function on the same type, with a similar use of Result for which the compiler has no trouble with:

pub fn expand_address(
    &self,
    a: &str,
    opts: ExpandAddressOptions,
) -> Result<Expansions, PostalError> {
    if self.setup_done && self.expand_address_enabled {
        let _ = self.mutex.lock();
        unsafe {
            match CString::new(a) {
                Ok(c_string) => {
                    let addr = c_string.as_ptr() as *mut c_char;

                    let mut num_expansions: usize = 0;
                    let raw = libpostal_expand_address(addr, opts.opts, &mut num_expansions);
                    Ok(Expansions::new(raw, num_expansions))
                }
                Err(e) => Err(PostalError::BadCString(e)),
            }
        }
    } else {
        Err(PostalError::LibpostalNotReady)
    }
}

What exactly is the compiler is having issues with in the former example?

I could (and might) change to Option<PostalError>, but that makes the match/unwrap/? awkward to use. I'd rather not, if possible.

Upvotes: 3

Views: 11111

Answers (1)

Nickolay
Nickolay

Reputation: 32063

 110 |             Err(PostalError::LibpostalSetup);
     |                 ^^^ cannot infer type for `T`

You missed a return.

Err(PostalError::LibpostalSetup); is a useless statement, not a function's return value, so I guess Rust is saying it has no way of inferring T in Result<T, PostalError> you're trying to construct.

"Function Bodies Contain Statements and Expressions" explains how the return value of a function is determined and "Are semicolons optional in Rust?" explains the significance of semicolons, or lack thereof, in Rust.

Upvotes: 9

Related Questions