These are chat archives for rust-lang/rust

8th
Feb 2018
dunnousername
@dunnousername
Feb 08 2018 00:13
Now, when using cargo build, I'm getting
error[E0432]: unresolved import `super::tokens`
 --> src/lang.rs:2:13
  |
2 |     use super::tokens::{An,Expression,Function};
  |                ^^^^^^ Could not find `tokens` in `super`

error[E0425]: cannot find function `x` in module `lang`
 --> src/main.rs:5:11
  |
5 |     lang::x();
  |           ^ not found in `lang`
help: possible candidate is found in another module, you can import it into scope
  |
1 | use lang::lang::x;
  |
I don't want lang::lang, I want lang. And why isn't it recognizing super::tokens, in main.rs, I have pub mod tokens;
Alexandre Bury
@gyscos
Feb 08 2018 00:15
Why super from main?
dunnousername
@dunnousername
Feb 08 2018 00:15
super is not in main, it is in lang.rs
use super::tokens::{An,Expression,Function}; in lang.rs, and mod tokens and mod lang in main.rs
Alexandre Bury
@gyscos
Feb 08 2018 00:16
It's hard to know without seeing the full code
What is the full lang.rs for instance?
dunnousername
@dunnousername
Feb 08 2018 00:21
pub mod lang {
    use super::tokens::{An,Expression,Function};
    pub fn x() {
        println!("x");
    }
}

That's lang.rs, the rest is commented out.

pub mod tokens { ... }

That's tokens.rs,
main.rs is

mod tokens;
mod lang;

fn main() {
    lang::x();
}
It's all in the same directory level
Alexandre Bury
@gyscos
Feb 08 2018 00:21
I see the problem
You shouldn't re-define pub mod lang in lang.rs
The content of lang.rs is already virtually included in a mod lang { ... } in main.rs
dunnousername
@dunnousername
Feb 08 2018 00:22
Is it assumed to be mod lang if it's in lang.rs?
Ohhh I see, C-style includes?
Alexandre Bury
@gyscos
Feb 08 2018 00:22
mod lang; means "define a mod lang with the content of the lang.rs file"
(Or the lang/mod.rs file)
dunnousername
@dunnousername
Feb 08 2018 00:23
Aha it works now
Thanks
dunnousername
@dunnousername
Feb 08 2018 00:25
Is it possible to match against the type of a generic function? I can't match T for some reason now
I want to convert the types into names of C types, e.g. i32 -> int32_t
Alexandre Bury
@gyscos
Feb 08 2018 00:25
?
Much like in C++, the T ends up replaced at compilation with the actual type (during monomorphization)
So at runtime, there is no T, only i32 for instance
dunnousername
@dunnousername
Feb 08 2018 00:27
pub fn type_name<T>() -> &'static str {
    match T {
        i32 -> return "int32_t",
        u32 -> return "uint32_t"
    }

    return "";
}
Something like that
Kind of like how size_of<T> works
Alexandre Bury
@gyscos
Feb 08 2018 00:27
So what you can do is define a new trait, ToCName
That has a single method get_name(&self) -> &str or something
And define it for i32 where it returns int32_t, and so on
dunnousername
@dunnousername
Feb 08 2018 00:28
Oh wow, I totally forgot about that entire aspect of the language haha
Alexandre Bury
@gyscos
Feb 08 2018 00:28
Then you just can call t.get_name() if you know that T: ToCName
dunnousername
@dunnousername
Feb 08 2018 00:28
So a where T: ToCName
Alexandre Bury
@gyscos
Feb 08 2018 00:28
Yup
dunnousername
@dunnousername
Feb 08 2018 00:29
and an impl ToCName for i32
Alexandre Bury
@gyscos
Feb 08 2018 00:29
Correct
And for every type you want to support
dunnousername
@dunnousername
Feb 08 2018 00:29
That just made everything so much easier, thanks
Alexandre Bury
@gyscos
Feb 08 2018 00:29
No problem ;)
Actually the get_name method doesn't even need to take &self
It can take zero argument
And you can call it with T::get_name()
dunnousername
@dunnousername
Feb 08 2018 00:30
I was wondering if it did
So then I can call it on the type itself
dunnousername
@dunnousername
Feb 08 2018 01:02

Huh, so I did

impl<T> ToCName for An<T> where
    T: ToCName {
    fn get_name() -> &'static str {
        return T::get_name();
    }
}

but when I catch an instance of An<T> I get

error[E0599]: no method named `get_name` found for type `tokens::An<T>` in the current scope
  --> src/lang.rs:25:25
   |
25 |                     print!("{} {};", x.get_name(), z)
   |                                        ^^^^^^^^
   | 
  ::: src/tokens.rs
   |
4  | pub enum An<T> {
   | -------------- method `get_name` not found for this
   |
   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
   = help: try with `tokens::An<T>::get_name`
x is an An<T>
Oh, it looks like I need to get the type from x. Can you not call functions without &self from an instance?
I.e. static, Java/C++-wise
Dylan DPC
@Dylan-DPC
Feb 08 2018 06:53
@dunnousername the error message tells you to how to solve your issue (check last line of screenshot)
Alexandre Bury
@gyscos
Feb 08 2018 07:00
@dunnousername Nah, calling static methods should take the type
Not the instance
(Which is fine, since you always have the type if you have the variable)
(Calling static methods on instances in java and C++ is often confusing anyway)
cryptopatrick
@cryptopatrick
Feb 08 2018 10:28

Hi Is it possible to do this:
In a file called foo.rs I have simple function.
In a separate file (in the same folder) I have a file called foo_test.rs.
In foo_test.rs I want to unit test the function located in foo.rs.

I know that I can place the test code as a submodule in foo.rs but I would like to seperate the test code into a separate file and still be able to test private methods.

Aleksey Kladov
@matklad
Feb 08 2018 10:30
The following should work
foo/
  mod.rs # function lives here
  tests.rs # tests live here
in foo/mod.rs, you write #[cfg(test)] mod tests;, in tests.rs you write use super::*;.
Daniel Bischof
@dbischof90
Feb 08 2018 10:33
Why do we need the super::*?
Aleksey Kladov
@matklad
Feb 08 2018 10:34
To get access to all private items from the parent module.
cryptopatrick
@cryptopatrick
Feb 08 2018 10:34
@matklad Thank you!!! Will try this out.
Daniel Bischof
@dbischof90
Feb 08 2018 10:35
Would the parent module in this case be foo?
Aleksey Kladov
@matklad
Feb 08 2018 10:35
yep, its name would be foo.
Daniel Bischof
@dbischof90
Feb 08 2018 10:35
Okay :)
Thanks
Sander Maijers
@sanmai-NL
Feb 08 2018 10:50
Seems this fork is a leftover and should be removed now? https://github.com/rust-lang/compiler-rt
cryptopatrick
@cryptopatrick
Feb 08 2018 14:16

Hi again! I got some help earlier but now I have a new problem related to testing files.
In the following gist I'm trying to test two files, add_test.rs and sub_test.rs but running cargo test returns "running 0 tests".

What should be in the cargo.toml file for cargo test to pick both tests files up for testing? Sorry if I'm posting this question in the wrong forum.
https://gist.github.com/cryptopatrick/db220b5c9d0002a5f860cf407b1056ac

Aleksey Kladov
@matklad
Feb 08 2018 14:21
@cryptopatrick you don't have lib.rs file
So, I'll try to clear up confusion a bit. I'll be talking about modules in general, tests are not actually relevant here.
In Rust, all code is organized in crates
cryptopatrick
@cryptopatrick
Feb 08 2018 14:22
Okay, thanks! What can I put in the lib.rs file so that the add.rs and sub.rs files are reached?
Aleksey Kladov
@matklad
Feb 08 2018 14:22
a crate is a tree of modules
You can always specify a whole crate in a single file
mod foo {
   mod nested {

   }

   mod nested2  {

   }
}
However, this is not convenient. It is possible to mechanically convert mod foo { /* body of foo */ } into mod foo; and a separate file foo.rs which contains /* body of foo */.
The compiler than pretty much literally would read the contents of foo.rs and append it to mod foo; so it looks like mod foo { /* body of foo */} again.
However, there's a restriction as to where mod foo; syntax can appear.
Specifically, it can appear in the top-level file of a crate (lib.rs or main.rs typically), or in a file with mod.rs name.
TL;DR: think of "modules", not of files.
cryptopatrick
@cryptopatrick
Feb 08 2018 14:26
Thanks A LOT for this!! Very much appreciated!
I'm coming from Golang so I'm used to simply do add.go and add_test.go and then run go test
Aleksey Kladov
@matklad
Feb 08 2018 14:27
So, for your example, I think the following would work
src/
  lib.rs # mod add; mod sub;
  sub/
    mod.rs # mod test;
    test.rs
  add
    mod.rs # mod test;
    test.rs
cryptopatrick
@cryptopatrick
Feb 08 2018 14:29
Hmm, that would really clutter up a project with 25 files. I would get 25 folders, one for each file and its test - I guess.
Dylan DPC
@Dylan-DPC
Feb 08 2018 14:30
you can put multiple files in a folder right?
Aleksey Kladov
@matklad
Feb 08 2018 14:31

Commonly, tests are not extracted into a separate file and live as an inline module.

And when they are extracted, it usually means that the modules itself is pretty large and is already split over several files (i.e, it is a directory module).

cryptopatrick
@cryptopatrick
Feb 08 2018 14:32
Yes, I understand. I'm just trying to see if it's possible to test files the way I'm used to. Okay, thanks! I'll try and solve it using your help! Again thank you very very much!
Aleksey Kladov
@matklad
Feb 08 2018 14:34
@cryptopatrick bear in mind, that Rust's crate/module system is rather unique. It has its strong and weak points, and trying to adapt, e.g., Go layout may hit a lot of weak points :- )
Zakarum
@omni-viral
Feb 08 2018 14:35
If I have a function foo<T>() -> Box<Trait<T>> how I need to change foo's signature to be able to create Box<for<'a> Trait<&'a u32>> in some particular case?
Kelly Thomas Kline
@kellytk
Feb 08 2018 14:35
@matklad Please consider writing a comparative article on Rust's crate system and submit it to the usual places
cryptopatrick
@cryptopatrick
Feb 08 2018 14:37
@matklad Yes! I just think that the Go solution is simple - why complicate things - this is just about separating code and tests in to different files. But, I'm new to the language so I really just expressing newbie fustration. Thanks for all the great help!
red75prime
@red75prime
Feb 08 2018 14:39
@omni-viral fn foo<'a, T: 'a>() -> Box<Trait<T> + 'a>
Zakarum
@omni-viral
Feb 08 2018 14:39
@red75prime Box<Trait<&'a u32> + 'a> and Box<for<'a> Trait<&'a u32>> are different things
Aleksey Kladov
@matklad
Feb 08 2018 14:40
@kellytk I've written a bit about crates (not modules) here: https://users.rust-lang.org/t/cargo-test-internal-packages/5187/8?u=matklad :)
red75prime
@red75prime
Feb 08 2018 14:43
@omni-viral 'a is not constrained by input parameters. Compiler is free to choose fitting one.
Zakarum
@omni-viral
Feb 08 2018 14:45
@red75prime In the first case 'a is concrete. In the second it is unbound.
For example if Trait<T> has this method fn foo(x: T) {} then with Box<for<'a> Trait<&'a u32>> you can call foo method with any reference
red75prime
@red75prime
Feb 08 2018 14:45
But the only fitting choice is 'static
Kelly Thomas Kline
@kellytk
Feb 08 2018 14:46
Cool @matklad
Zakarum
@omni-viral
Feb 08 2018 14:47
trait Trait<T> {
  fn foo(&self, _: T) {}
}

let x: Box<for<'a> Trait<&'a u32>> = ... // lifetime is unbound
let y: Box<Trait<&u32>> = ... // lifetime is concrete
let z: u32 = 2;
x.foo(&z); // Ok
y.foo(&z); // Error
The sad part is that for<'a> Trait<&'a u32> cannot be returned by function foo<T>() -> Box<Trait<T>>
Even worse. If you have struct X<T>(Box<Trait<T>>) you can't put Box<for<'a> Trait<&'a u32>> there without having it converted into Box<Trait<&u32>>
red75prime
@red75prime
Feb 08 2018 14:51
It seems you need type constructor in place of a type.
Box<for<'a> Trait<T<'a>>>
Zakarum
@omni-viral
Feb 08 2018 14:52
Looks like it
dunnousername
@dunnousername
Feb 08 2018 14:56
$ cargo run
...
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
... (version switch)
$ cargo --version
cargo 0.26.0-nightly (1d6dfea44 2018-01-26)
$ cargo run -Z external-macro-backtrace
error: unknown `-Z` flag specified: external-macro-backtrace
I'm not sure what is wrong
I'm trying to use nom, and am getting weird error messages
It happens with cargo build as well...
Steve Klabnik
@steveklabnik
Feb 08 2018 14:59
naw you'd need
cargo rustc -- -Z external-macro-backtrace
this error isn't that great :/
maybe cargo run -- -Z external... works
not sure
dunnousername
@dunnousername
Feb 08 2018 15:00
I'll try that
Woah I turned on verbose errors for nom and they are like twice the size of my terminal window
cargo run doesn't work, sadly
But you wouldn't need it if you knew it was going to error
error: no rules expected the token `i_`
  --> src/main.rs:6:2
   |
6  |       named!(mul<i64>, do_parse!(
   |  _____^
7  | |             x: i32!() >>
8  | |             a: char!("*") >>
9  | |             y: i32!() >>
...  |
12 | |         )
13 | |     );
   | |______^
   |
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
Macros are evil
All external-macro-backtrace does is show the macro expansion, but I've never understood how macros work
72  | |||||  __impl i_ , $ consumed + (
    | |||||         ^^
73  | |||||  $ crate :: InputLength :: input_len ( & ( $ i ) ) - $ crate :: InputLength ::
74  | |||||  input_len ( & i ) ) , $ ( $ rest ) * ) } , } } ) ; (
Just a lot of braces, brackets, symbols and pipes
Martin Hafskjold Thoresen
@martinhath
Feb 08 2018 15:10
Hey all, why does foo work, but not bar?
struct S;
fn id(s: &S) -> &S { s }
fn foo() { let _f = id(&S); }
fn bar() { let _f = id(&mut S); }
(it says borrowed value does not live long enough)
Steve Klabnik
@steveklabnik
Feb 08 2018 15:11
i have a sneaking suspicion but am not totally sure
dunnousername
@dunnousername
Feb 08 2018 15:29
    named!(mul <i64>, do_parse!(
            x: num >>
            //a: char!("*") >>
            y: num >>
            res: (x as i64) + (y as i64) >>
            res
        )
    );
Is this proper syntax?
It keeps giving me the i_ errors
Roman Proskuryakov
@kpp
Feb 08 2018 15:30
the last (res)
should be in ( )
dunnousername
@dunnousername
Feb 08 2018 15:31
I tried that I thought... let me try again
Still gives an error
Roman Proskuryakov
@kpp
Feb 08 2018 15:31
yes
res: (x as i64) + (y as i64) - wrong
you should put "type" after :
or a function that will parse string and return you some result
so in your case:
dunnousername
@dunnousername
Feb 08 2018 15:32
I thought : acted as an = operator in this macro
Roman Proskuryakov
@kpp
Feb 08 2018 15:32
    named!(mul <i64>, do_parse!(
            x: num >>
            //a: char!("*") >>
            y: num >>
            ((x as i64) + (y as i64))
        )
    );
dunnousername
@dunnousername
Feb 08 2018 15:34
Can I make a &[u8] literal?
From a string
error[E0603]: module `str` is private
 --> src/main.rs:5:17
  |
5 | use nom::{digit,str};
  |                 ^^^
with str::from_utf8
Roman Proskuryakov
@kpp
Feb 08 2018 15:35
???
what is a string?
dunnousername
@dunnousername
Feb 08 2018 15:35
Oops two errors
Okay, now the problem is it can't find from_utf8 in str
Wait no what am I doing, hold on I just blew up my head
I need to convert to i32 not string
Roman Proskuryakov
@kpp
Feb 08 2018 15:39
Zakarum
@omni-viral
Feb 08 2018 16:08
@red75prime I think I found solution
Instead of having Box<for<'a> Trait<T<'a>>> I have Box<Y> and require Y: Trait<T> for whatever T I have as method parameter
And of course for<'a> Trait<&'a T> implements Trait<&'a T> for any 'a
Patrick Elsen
@xfbs
Feb 08 2018 22:48
Is there anywhere a tutorial on how to write your own iterator adaptor in rust?
I'm kinda strugglin here
Aleksey Kladov
@matklad
Feb 08 2018 22:57
@xfbs I can suggest reading the source of standard iterators and of the itertools crate
Ashley Mannix
@KodrAus
Feb 08 2018 23:16
@xfbs Here's another example showing how you could create your own adapter and then make it available on any iterator to call: http://play.integer32.com/?gist=96388904bfaea1602db0cc0effca39f4&version=stable
The gist of it is that you create a struct for your adapter, implement Iterator for it, and then use an extension trait to make it available to call on other iterators
Patrick Elsen
@xfbs
Feb 08 2018 23:20

Oh my gosh, thanks guys! I'm so stupid — I was missing one line:

impl<T: ?Sized> MyIterator for T where T: Iterator { }

which explains why it didn't work (as I wanted it to). Oops.

Ashley Mannix
@KodrAus
Feb 08 2018 23:48
:) Glad you got it sorted!