Question

Consider the following contrived situation:

mod imported {
    pub trait Imported {
        fn hello(&self, x:int) -> int;
    }
}

struct Hi;

impl imported::Imported for Hi {
    fn hello(&self, x:int) -> int {
        return x;
    }
}

#[test]
fn test_thing() {
    let value = Hi;
    println!("{:?}", value.hello(10));
}

This won't compile, because the trait Imported is not in scope, so the method hello() cannot be invoked:

imports.rs:20:18: 20:33 error: type `imports::Hi` does not implement any method in scope named `hello`
imports.rs:20   println!("{:?}", value.hello(10));
                                 ^~~~~~~~~~~~~~~

If we put Imported in the current scope (ie. get rid of mod imported) this works fine, but like this, it does not.

Normally for this purpose you would use 'use' to bring the 'Imported' symbol into the local scope:

use imported::Imported; 

However, in this case you cannot, because the symbol 'imported' does not yet exist at the beginning of the file:

imports.rs:2:5: 2:13 error: unresolved import. maybe a missing `extern crate imported`?
imports.rs:2 use imported::Imported;
                 ^~~~~~~~
imports.rs:2:5: 2:23 error: failed to resolve import `imported::Imported`
imports.rs:2 use imported::Imported;
                 ^~~~~~~~~~~~~~~~~~

And you cannot do it after the mod imported call, because:

imports.rs:8:1: 8:24 error: `use` and `extern crate` declarations must precede items
imports.rs:8 use imported::Imported;
             ^~~~~~~~~~~~~~~~~~~~~~~

To be fair this only occurs when you are implementing a trait and then trying to use that impl in the safe file, but it seems like this would actually be quite a common use case for testing.

You can work around it by structuring your code slightly differently and importing modules from some common parent, but this seems like an inherent limitation of the current system.

Am I missing something?

Was it helpful?

Solution

I think you have indeed missed something. Adding use imported::Imported; at the top of the file does work—I presume that this is not precisely what you tried to compile.

use statements, although written before the mod statements, are resolved after the mod, so there is no source order problem.

I presume that your error is in fact that your file imports.rs was not the crate root. Remember that a use statement takes an absolute path if you don't use super or self in it. To make it work in any place, you would need to write use self::imported::Imported;; assuming you were compiling a lib.rs containing mod imports;, you would have needed to use imports::imported::Imported, the absolute path to the trait.

(BTW, you can replace return x; at the end of the function with just x. Remember Rust's block value doctrine, whereby the last expression in a block is the value of the block.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top