These are chat archives for rust-lang/rust

2nd
Aug 2018
trsh
@trsh
Aug 02 2018 08:09
How do I declare that fn takes mutable pointer?
xx(xx: *mut Type) ?
qq00
@qq00
Aug 02 2018 08:29
is there a better way to write "while true; do cargo check; done;"
Denis Lisov
@tanriol
Aug 02 2018 08:46
@qq00 Installing cargo-watch
qq00
@qq00
Aug 02 2018 09:49
@tanriol : I am running "cargo watch -x check" which appears to be working, is this the intehnded solution?
Denis Lisov
@tanriol
Aug 02 2018 09:54
You can just run cargo watch, as check is the default command it runs
Heinz N. Gies
@Licenser
Aug 02 2018 11:18
afternoon folks, a quick question as I couldn't find an answer on google, how would I go about marking a single case for clippy to be 'OK' but not allow it everywhere?
Heinz N. Gies
@Licenser
Aug 02 2018 11:26
oh with some thinking I answered that myself :) its #[allow(...)] instread of #![allow(...)
qq00
@qq00
Aug 02 2018 15:00

How do I get
src/a/b/c/d.rs to use functions from
src/x/y.rs ?

writing "mod parent::parent::parent::x::y" seems really brittle + ugly

Heinz N. Gies
@Licenser
Aug 02 2018 15:01
I think just x::y::function works?
i.e. use x::x; x::foo()
qq00
@qq00
Aug 02 2018 15:03
use x::y; <- this seems to want me to first load "module x"

but to load module x, I have to do

mod parent::parent::parent::x;

Heinz N. Gies
@Licenser
Aug 02 2018 15:03
did you define mod x in your lib.rs or main.rs ?
I don't know if that's the ideomatic way to do things but that's how I've been doing it
qq00
@qq00
Aug 02 2018 15:04
not yet, let me try this
btw, I've read the "rust by example" section of mod/use, it's the one section of the book I still don't quite get
Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:05
@qq00, mod defines modules, use loads modules into the scope. You shouldn't have :: in a mod line.
qq00
@qq00
Aug 02 2018 15:06

when I hav:
src/main.rs
mod a;
src/a/mod.rs
pub mod b;
src/a/b.rs

what do the two above 'mod' lines do? I don't see them "defining" anything -- this confuses me

Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:07
use is actually optional, but very convenient if you're going to repeat yourself a lot. You could do ::x::y::function() in d.rs if you only need to do it once.
mod a; says there is a module called a, and rustc knows when there isn't a body for it (mod a {} defines the module inline), to look in the path "a/mod.rs" to get the contents of the module.
OR, there's "a.rs" in the same folder as the mod.rs that line is in.
qq00
@qq00
Aug 02 2018 15:09
This is useful. Let's take a step back and pretend to be the compiler.
  1. Rustc doesn't compile all the files in src/*/.rs right ?
  1. Instead, it looks at main.rs or lib.rs
  1. Instead, it looks at main.rs or lib.rs, and recursively chases down all the "mod" lines
  1. where when it sees "mod foo", it looks for either foo.rs or foo/mod.rs, and recursively loads *.rs files this way
Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:10
That sounds right.
qq00
@qq00
Aug 02 2018 15:10
BTW, that should be 1, 2, 3, 4 not 1, 1, 1, 1 above, no idea why gitten is renumbering all my numbers.
Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:10
I blame Markdown.
qq00
@qq00
Aug 02 2018 15:10
okay, so we have now defined the subset of *.rs files in /src/ that rust compiles
at this point, everything has a "long name" i.e. src/a/b/c/d.rs has stuff in it referred to as ::a:;b::c::d::func_name
and 'use' just allows us to define aliases ?
Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:11
That's what it's for.
qq00
@qq00
Aug 02 2018 15:11
Thanks! I finally get this now. :-)
Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:12
The tricky thing about use, (that's being changed in the 2018 edition), is that use doesn't take things that start with the initial ::.
qq00
@qq00
Aug 02 2018 15:12
I have a file "generated_bindings.rs" -- it triggers lots of warnings. Is there a compiler flag for "ignore all unused imports for this file" ?
Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:13
And, if you're in the crate root (main.rs or lib.rs), if you leave off that inital :: when you call things, it still works, because you're relative to the crate root.
#![allow(unused)] at the top of the file.
qq00
@qq00
Aug 02 2018 15:14
is #[] "next expr only" while #![] "apply to entikre file" ?
Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:15
#![] is the containing scope.
qq00
@qq00
Aug 02 2018 15:15

![] applies to the "smallest {} containing"? (and imagine the entire file has an outer {} ) ?

Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:15
So, at the top of the file, where there's nothing else around it, it means the whole file.
qq00
@qq00
Aug 02 2018 15:16
that extra bold is markdown, not me
Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:16
# starts headers
Kaspar Schiess
@kschiess
Aug 02 2018 15:27

This

    = note: expected type `std::boxed::Box<(dyn futures::Future<Item=http::Response<hyper::Body>, Error=hyper::Error> + std::marker::Send + 'static)>`
               found type `futures::Map<hyper::client::ResponseFuture, fn(http::Response<hyper::Body>) -> std::boxed::Box<(dyn futures::Future<Item=http::Response<hyper::Body>, Error=hyper::Error> + std::marker::Send + 'static)> {handle_response}>`

seems like 'not a problem' to me - still - the compiler complains. (nightly) How can I elide the map and the closure to yield just the expected type?

Zakarum
@omni-viral
Aug 02 2018 15:28
It expected Box<dyn Trait> you give it an impl Trait
Box::new should save you
Not really sure that you give it the right impl Trait though
It seems that you try to Future::map instead of Future::and_then
Kaspar Schiess
@kschiess
Aug 02 2018 15:32
I'll be frank; I guess the difference between these puzzles me. I'll try looking them up again, although I admit the last 4 hours didn't help ;) Can I show you some code, @omni-viral ?
Zakarum
@omni-viral
Aug 02 2018 15:33
Future::map takes impl Future<Output = T> and fn(T) -> U and returns impl Future<Output = U>
Future::and_then takes impl Future<Output = T> and fn(T) -> impl Future<Output = U> and returns impl Future<Output = U>
From the futures::Map parameters I see that your function returns a future. So it impl Future<Output = impl Future<Output = T>>
But you want to coerce it to impl Future<Output = T>
Btw. If you on nightly you should consider to use futures 0.3.0 preview which utilizes Future trait from std
Lyle Mantooth
@IslandUsurper
Aug 02 2018 15:37
I'm constantly getting Result::map and Result::and_then confused. Glad to know once it finally solidifies for me it works the same way for Futures.
Zakarum
@omni-viral
Aug 02 2018 15:37
It is nothing fancy if you wrote some haskell before :smile:
map is fmap and and_then is >>=
Kaspar Schiess
@kschiess
Aug 02 2018 15:38
Thanks @omni-viral - Still parsing the above, give me a sec.
So in essence, I was creating a double future, one inside the other - with no way of resolving the second one? And switching to and_then should 'hoist' the second future on the first level, allowing it to be resolved normally?
Zakarum
@omni-viral
Aug 02 2018 15:40
@kschiess when you have future of future there is Future::flatten
But it is better to use and_then instead of map and then flatten
While essentially it is the same and_then can work faster
Kaspar Schiess
@kschiess
Aug 02 2018 15:46
That makes a lot of sense. Is it possible that I have to complete the AndThen with an OrElse to get types to align on both execution paths?
   --> src/main.rs:138:5
    |
123 |   BoxFut {
    |   ------ expected `std::boxed::Box<(dyn futures::Future<Item=http::Response<hyper::Body>, Error=hyper::Error> + std::marker::Send + 'static)>` because of return type
...
138 | /     client
139 | |         .request(backend_req)
140 | |         .and_then(|res| handle_response(res))
    | |_____________________________________________^ expected struct `std::boxed::Box`, found struct `futures::AndThen`
    |
    = note: expected type `std::boxed::Box<(dyn futures::Future<Item=http::Response<hyper::Body>, Error=hyper::Error> + std::marker::Send + 'static)>`
               found type `futures::AndThen<hyper::client::ResponseFuture, std::boxed::Box<dyn futures::Future<Item=http::Response<hyper::Body>, Error=hyper::Error> + std::marker::Send>, [closure@src/main.rs:140:19: 140:45]>`
Zakarum
@omni-viral
Aug 02 2018 15:55
Aren't you have hyper::Error everywhere?
Kaspar Schiess
@kschiess
Aug 02 2018 15:55
I do. I was missing a Box::new on the toplevel; just as you said.
It now compiles; I'll try to put all the code I commented out back in...
Zakarum
@omni-viral
Aug 02 2018 15:56
And or_else converts error into future. To just convert error type there is map_err
Kaspar Schiess
@kschiess
Aug 02 2018 16:03
I've used from_err() - works nicely, but probably redundant. Anyhow.. it now complains about missing 'Sync' trait ;) I can't get a break today.
I'll box more stuff. - it says something about statically knowing the size of the return type.
Kaspar Schiess
@kschiess
Aug 02 2018 16:09

Mad error message spew:

149 | /     Box::new(
150 | |         res.into_body().concat2().map( |buf| {
151 | |             let text = std::str::from_utf8(buf.as_ref()).expect("valid utf8");
152 | |             analyse_response(&res, &text);
...   |
158 | |         })
159 | |     )
    | |_____^ `(dyn futures::Stream<Item=hyper::Chunk, Error=std::boxed::Box<(dyn std::error::Error + std::marker::Sync + std::marker::Send + 'static)>> + std::marker::Send + 'static)` cannot be shared between threads safely
    |
    = help: the trait `std::marker::Sync` is not implemented for `(dyn futures::Stream<Item=hyper::Chunk, Error=std::boxed::Box<(dyn std::error::Error + std::marker::Sync + std::marker::Send + 'static)>> + std::marker::Send + 'static)`
    = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<(dyn futures::Stream<Item=hyper::Chunk, Error=std::boxed::Box<(dyn std::error::Error + std::marker::Sync + std::marker::Send + 'static)>> + std::marker::Send + 'static)>`
    = note: required because it appears within the type `std::boxed::Box<(dyn futures::Stream<Item=hyper::Chunk, Error=std::boxed::Box<(dyn std::error::Error + std::marker::Sync + std::marker::Send + 'static)>> + std::marker::Send + 'static)>`
    = note: required because it appears within the type `hyper::body::body::Kind`
    = note: required because it appears within the type `hyper::Body`
    = note: required because it appears within the type `http::Response<hyper::Body>`
    = note: required because of the requirements on the impl of `std::marker::Send` for `&http::Response<hyper::Body>`
    = note: required because it appears within the type `[closure@src/main.rs:150:40: 158:10 res:&http::Response<hyper::Body>]`
    = note: required because it appears within the type `std::option::Option<[closure@src/main.rs:150:40: 158:10 res:&http::Response<hyper::Body>]>`
    = note: required because it appears within the type `futures::Map<futures::stream::Concat2<hyper::Body>, [closure@src/main.rs:150:40: 158:10 res:&http::Response<hyper::Body>]>`
    = note: required for the cast to the object type `dyn futures::Future<Item=http::Response<hyper::Body>, Error=hyper::Error> + std::marker::Send`

error: aborting due to previous error

I admit having no clue about this either.

Dmitriy
@dpogretskiy
Aug 02 2018 16:31
it just means not every stream is Sync, which is probably not true factually, but compiler can't prove otherwise :)
what's the return type you expect from it?
Kaspar Schiess
@kschiess
Aug 02 2018 16:43
I found it: I had to 'move' the 'res' variable (Response<Body>) into the closure after 'map', otherwise I would (possibly) access it from two threads at the same time. The message was correct, if a bit ... bad for Rust's image.
When I get these kind of messages, I am always first angry - and then glad. Oh Well.
Anyhow; my thingy works well enough now, back to designing the overall project. Thanks for all your help!
Sander Maijers
@sanmai-NL
Aug 02 2018 17:39
@kschiess: In my experience the opaqueness of compilation error messages in your code is strongly related to the degree of complexity of components you’re using. hyper is one example that is quite complex IMO. It’s sad a number of basic, popular components suffer from this.
qq00
@qq00
Aug 02 2018 20:25

If I want to add a new "member function" to an struct, do I have to:

  1. define a new trait
  2. have the struct implement the trait

==

Is there a way around this, without first defining a trait?

Dmitriy
@dpogretskiy
Aug 02 2018 20:28
you can impl StructName
Lyle Mantooth
@IslandUsurper
Aug 02 2018 20:31
You can even impl StructName in multiple different modules.
Dmitriy
@dpogretskiy
Aug 02 2018 20:32
no, only where the struct itself lives
Lyle Mantooth
@IslandUsurper
Aug 02 2018 20:32
False, I've done it.
Different modules, but not different crates.
Dmitriy
@dpogretskiy
Aug 02 2018 20:33
i've never tried to make multiple impl for a single struct
Lyle Mantooth
@IslandUsurper
Aug 02 2018 20:34
I can imagine it's not a great idea. If you have so many functions on a struct that you need to break the impl apart, you're probably doing something wrong design-wise.
But it's possible.
Denis Lisov
@tanriol
Aug 02 2018 20:37
You can have multiple impls that have different bounds, for example. Say, one for any T and another with the T: Sized bound.
qq00
@qq00
Aug 02 2018 20:37
Got it, just
impl Struct_I_want_to_extend {
...
}

In this code, I am getting an error "undeclared lifetime" referring to the 'a. The code is:

struct Shader<'a> {
    context: &'a GL,
    shader_id: webgl::WebGLShader,
}

#[allow(dead_code)]
impl Drop for Shader<'a> {
    fn drop(&mut self) {
        let context = & self.context;
        let shader_id = & self.shader_id;
        context.delete_shader(Some(shader_id));
    }
}

How do I fix this?

Lyle Mantooth
@IslandUsurper
Aug 02 2018 20:41
impl<'a> Drop for Shader<'a> {
qq00
@qq00
Aug 02 2018 20:45
This works; thanks!
Justin Kilpatrick
@jkilpatr
Aug 02 2018 22:34
how in the world do I propogate futures errors properly?
expected struct futures::Then, found enum actix_web::client::SendRequestError