The true return type of this function

I am a freshman of Rust, and I am coding a module which implements microsoft oauth login. But I encountered an error which told me this:

type alias takes 1 generic argument but 2 generic arguments were supplied
expected 1 generic argumentrustcClick for full compiler diagnostic
error.rs(9, 10): type alias defined here, with 1 generic parameter: `T`
microsoft.rs(25, 60): remove this generic argument

Here is the function I wrote:

pub async fn get_access_token(&mut self) -> Result<(), Box<dyn std::error::Error>>
    {
        let mut map = HashMap::new();
        map.insert("client_id", "00000000402b5328");
        map.insert("code", &self.auth_code);
        map.insert("grant_type", "authorization_code");
        map.insert("redirect_uri", "https://login.live.com/oauth20_desktop.srf");
        map.insert("scope", "service::user.auth.xboxlive.com::MBI_SSL");
        
        let client = Client::new();
        let result = client
            .post("https://login.live.com/oauth20_token.srf")
            .json(&map)
            .send()
            .await?
            .text()
            .await?;

        let json_access_token: Value = serde_json::from_str(&result)?;

        self.access_token = json_access_token.get("access_token").unwrap().as_str().unwrap().to_string();
        Ok(())

I used two crates to code my project: serde_json and reqwest.
I then wrote this code to import crates in my source file:

use std::collections::HashMap;
use serde_json::Value;
use reqwest::*;

Due to I am new here, I might make some mistakes. Thanks for your help!

I would guess there might be a Result exported from the reqwest crate, which is an alias. use the full path std::result::Result, or remove the wildcard import and only import what you actaully used.

I'd assume your import of reqwest::* means Result in reqwest - Rust is used.

Importing all items from a module that is not designed for you do to this is a bit of an anti-pattern. Some modules that are designed to be used like that are typically called 'prelude' but the top level of the reqwest crate isn't, as far as aware. Expecially as you seem to be using an IDE anyway, it's really straightforwart to explicitly do a use reqwest::{the, list, of, what, you, actually, need};-style import instead.

Nonetheless, even without removing the use reqwest::*;, you could also replace the -> Result<…> return type with a full path -> std::result::Result<…>.

1 Like

Well, I modified the import as use reqwest::Client and then I met another error:

the size for values of type `str` cannot be known at compilation time
the trait `Sized` is not implemented for `str`
all local variables must have a statically known size
unsized locals are gated as an unstable feature

this error appears at this code:

let result = client
            .post("https://login.live.com/oauth20_token.srf")
            .json(&map)
            .send()
            .await?
            .text()
            .await?;

As for writing the full path std::result::Result, it will also encounters this error above.

Okay… here’s a tip on writing better questions in this forum. Don’t copy the error message from your IDE. Instead open a terminal, navigate to your Rust project, and run cargo check. Then copy the full error message you get there. The compiler will give some visually good error message that

  • are a lot easier to read
  • make it clear what point in the code what part of the message points to
  • make it clear, what part of the message is the main error, which parts are further explanations, which parts are additional help or suggestions, etc
6 Likes

Ok. I got these errors by following your tips:

error[E0599]: no method named `json` found for struct `RequestBuilder` in the current scope
  --> gcl-core\src\auth\microsoft.rs:37:14
   |
35 |           let result = client
   |  ______________________-
36 | |             .post("https://login.live.com/oauth20_token.srf")
37 | |             .json(&map)
   | |             -^^^^ method not found in `RequestBuilder`
   | |_____________|
   |

error[E0277]: the size for values of type `str` cannot be known at compilation time
  --> gcl-core\src\auth\microsoft.rs:35:13
   |
35 |         let result = client
   |             ^^^^^^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `str`
   = note: all local variables must have a statically known size
   = help: unsized locals are gated as an unstable feature

error[E0277]: the size for values of type `str` cannot be known at compilation time
  --> gcl-core\src\auth\microsoft.rs:35:22
   |
35 |           let result = client
   |  ______________________^
36 | |             .post("https://login.live.com/oauth20_token.srf")
37 | |             .json(&map)
38 | |             .send()
39 | |             .await?
40 | |             .text()
41 | |             .await?;
   | |___________________^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `str`
   = note: all local variables must have a statically known size
   = help: unsized locals are gated as an unstable feature

error[E0277]: the size for values of type `str` cannot be known at compilation time
  --> gcl-core\src\auth\microsoft.rs:41:19
   |
41 |             .await?;
   |                   ^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `str`
note: required by a bound in `Break`
  --> C:\Users\TheBlueAlgae\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\core\src\ops\control_flow.rs:85:25
   |
85 | pub enum ControlFlow<B, C = ()> {
   |                         ^^^^^^ required by this bound in `Break`
1 Like

You need to enable the json feature for reqwest in your Cargo.toml file:

[dependencies]
reqwest = { version = "0.11", features = ["json"] }

The error message regarding str and sizes is interesting. Looks like the compiler does, as it often does, continue compilation a little even though the .json() method was not found. This then has the effect that the type of result is not known from it’s right-hand-side expression as that expression failed to be analyzed properly due to the unknown method. Then it looks like the call to serde_json::from_str(&result) is taken as a hint for the type of result. While if result is a String, this kind of call works because &String coerces into &str implicitly, with limited type information, type inference rules out coercion and infers result to be str. This inference then leads to the compiler complaining about result having an unsized type.

I’d say this is a bit of a problematic diagnostic, though I’m not sure if it’s easy to improve without possibly worsening compiler output in other cases.

In any case, it’s a good practice, when using the Rust compiler, not to focus completely on just a single error message (or even worse, a single warning) when other error messages are present, too. As is the case in this case, there’s a different error that’s easier to understand, and causes the other error only as a follow-up.

I’m not certain either if the fact that the more relevant error was first was just good luck, or if that’s commonly the case for one error “causing” other follow-up ones; but it certainly doesn’t hurt to look at the first error in particular.

Especially if there’s multiple errors present, this means that the terminal output of Rust can be giving a better overview as to what’s going on than the IDE-integrated display of errors, as you see everything with complete information in a single place. In this case in particular, I also assume that the IDE displayed the the size for values of type `str` cannot be known at compilation time error a lot more prominently due to the fact that its span (the “problematic” code it points to, commonly red squiggles in IDEs) is a lot larger, and even contains the main error’s span; the error messages in the terminal do a better job at separately listing all the errors individually so nothing can be missed so easily.

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.