Why do I need to import a trait to use the methods it defines for a type?

Rust

Rust Problem Overview


I have a very simple example of Rust code which fails to compile:

extern crate rustc_serialize;
use rustc_serialize::base64;

fn main() {
    let auth = format!("{}:{}", "user", "password");
    let auth_b64 = auth.as_bytes().to_base64(base64::MIME);
    println!("Authorization string: {}", auth_b64);
}

The compiler error:

error[E0599]: no method named `to_base64` found for type `&[u8]` in the current scope
 --> src/main.rs:6:36
  |
6 |     let auth_b64 = auth.as_bytes().to_base64(base64::MIME);
  |                                    ^^^^^^^^^
  |
  = help: items from traits can only be used if the trait is in scope
  = note: the following trait is implemented but not in scope, perhaps add a `use` for it:
          candidate #1: `use rustc_serialize::base64::ToBase64;`

It works if I import the trait explicitly:

extern crate rustc_serialize;

use rustc_serialize::base64::{self, ToBase64};

fn main() {
    let auth = format!("{}:{}", "user", "password");
    let auth_b64 = auth.as_bytes().to_base64(base64::MIME);
    println!("Authorization string: {}", auth_b64);
}

Why do I need to use rustc_serialize::base64::ToBase64;?

Rust Solutions


Solution 1 - Rust

That’s simply the way it is. In Rust a trait must be in scope for you to be able to call its methods.

As for why, the possibility of collisions is the reason why. All the formatting traits in std::fmt (Display, Debug, LowerHex, &c.) have the same method signature for fmt. For example; what would object.fmt(&mut writer, &mut formatter) do, for example? Rust’s answer is “you must explicitly indicate by having the trait in scope where the method is.”

Note also how the error message says that “no method named `m` found for type `T` in the current scope”.

Note that you don't have to import it if you want to use the trait method as a function instead of a method:

extern crate rustc_serialize;

use rustc_serialize::base64;

fn main() {
    let auth = format!("{}:{}", "user", "password");
    let auth_b64 = rustc_serialize::base64::ToBase64::to_base64(auth.as_bytes(), base64::MIME);
    //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    println!("Authorization string: {}", auth_b64);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmhristacheView Question on Stackoverflow
Solution 1 - RustChris MorganView Answer on Stackoverflow