Principles for Implicits in Scala 3

That’s exactly the case in my Rust example presented here: Principles for Implicits in Scala 3 - #16 by tarsa

I provided an example where all definitions are placed in one file which can be misleading. Consider instead a multi-file project with following files:

struct_here.rs:

pub struct MyStruct;

impl MyStruct {}

traits/mod.rs:

pub mod trait_here;

traits/trait_here.rs:

use struct_here::MyStruct;

pub trait MyTrait {
    fn print_hello(&self);
}

impl MyTrait for MyStruct {
    fn print_hello(&self) {
        println!("Hello, World!")
    }
}

and finally the main file (library entry point) lib.rs:

pub mod struct_here;
pub mod traits;

use struct_here::MyStruct;

fn entry_point() {
    let instance = MyStruct {};
    instance.<caret is here>
}

At the specified place IntelliJ suggests me that I can use print_hello() method on instance of type struct_here::MyStruct. Note that traits::trait_here::MyTrait is not yet imported (with use keyword). Also struct_here/MyStruct.rs doesn’t have any reference to traits::trait_here::MyTrait so IntelliJ really need to scan everything to provide relevant suggestion.

When I choose the suggestion final code looks like this (lib.rs):

pub mod struct_here;
pub mod traits;

use struct_here::MyStruct;
use traits::trait_here::MyTrait; // automatically added line by IntelliJ

fn entry_point() {
    let instance = MyStruct {};
    instance.print_hello(); // print_hello from autocomplete
}

Rust compiler does similar job to IntelliJ, but in non-interactive way. Rust compiler doesn’t provide auto-complete, but it does suggest relevant import (use) clause when compilation fails.

There’s also a question why we must import the traits in Rust to make them useable. Answer is simple - with all traits implicitly imported there would be name clashes. Consider this: IeObsi - Online IDE & Debugging Tool - Ideone.com

mod my_struct {
    pub struct MyStruct {}
}

mod traits_1 {
    pub trait Trait1 {
        fn print(&self);
    }

    impl Trait1 for ::my_struct::MyStruct {
        fn print(&self) {
            println!("Good morning!");
        }
    }
}

mod traits_2 {
    pub trait Trait2 {
        fn print(&self);
    }

    impl Trait2 for ::my_struct::MyStruct {
        fn print(&self) {
            println!("Goodbye!");
        }
    }
}

fn main() {
    use traits_1::Trait1;
    use traits_2::Trait2;

    let instance = my_struct::MyStruct {};
    println!("{}", instance.print());
}

Result:

error[E0034]: multiple applicable items in scope
  --> src/main.rs:35:29
   |
35 |     println!("{}", instance.print());
   |                             ^^^^^ multiple `print` found
   |
note: candidate #1 is defined in an impl of the trait `traits_1::Trait1` for the type `my_struct::MyStruct`
  --> src/main.rs:12:9
   |
12 |         fn print(&self) {
   |         ^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl of the trait `traits_2::Trait2` for the type `my_struct::MyStruct`
  --> src/main.rs:24:9
   |
24 |         fn print(&self) {
   |         ^^^^^^^^^^^^^^^