These are chat archives for rust-lang/rust

8th
Nov 2018
aohan237
@aohan237
Nov 08 2018 02:16
@kpp actix-web have the solutions
    req: Request<Body>,
) -> Box<Future<Item = Response<Body>, Error = hyper::Error> + Send> {
    let url_matched = self.match_re_url(&req);
    let mut aa = &mut req;
this req is the owner why cant make mut borrow
aohan237
@aohan237
Nov 08 2018 02:22
i know where is the problem..
aohan237
@aohan237
Nov 08 2018 09:15
i have another question. i own the struct , then i have a mut borrow, then i have another unmut borrow. then ide say conflict why?
Dmitriy
@dpogretskiy
Nov 08 2018 09:26
you can't mutate something and read at the same time
Zakarum
@omni-viral
Nov 08 2018 09:48
Mut borrow still alive I guess
Roman Proskuryakov
@kpp
Nov 08 2018 10:22
@aohan237 actix-web is based on tokio. tokio is based on mio. mio is based on [e]/poll|kqueue, and there is no way to build it on wasm since wasm target does not contain poll functions.
I checked it half a year ago. If things changed since that time I would be grateful if you send me a working example of actix-web client built for wasm
Roman Proskuryakov
@kpp
Nov 08 2018 10:34
aohan237
@aohan237
Nov 08 2018 10:50
@omni-viral they in the same scope. first ,a fn needs a mut borrow,then another fn needs a unmut borrow. so the mut borrow is alive.....but in this cirrumstance ,what should i do ?
Denis Lisov
@tanriol
Nov 08 2018 10:51
@aohan237 What does the function that uses the mutable borrow return?
aohan237
@aohan237
Nov 08 2018 10:51
@dpogretskiy i have a mut borrow first,then i dont need it
i use hyper
@tanriol
i want to store something to hyper.extenteion
this needs a mut borrow
then i want store req.uri().path() to hyper.extention
this require unmut borrow
Denis Lisov
@tanriol
Nov 08 2018 10:52
Can you show the code snippet that causes the problem?
aohan237
@aohan237
Nov 08 2018 10:53
so i cant do this in one fn
now i have use other ways to bypass it...
it will take some time to show you the snippet
Denis Lisov
@tanriol
Nov 08 2018 10:55
Sure you can do that in one function...
aohan237
@aohan237
Nov 08 2018 10:55

cannot borrow *req as mutable because it is also borrowed as immutable

mutable borrow occurs here

this is the sinppet
Denis Lisov
@tanriol
Nov 08 2018 11:01
Oh... sorry, there's one problem with what you're trying to do. req.uri().path() is a reference into data the request owns, so it cannot be stored on the same request. You'll likely need to clone it.
aohan237
@aohan237
Nov 08 2018 13:43
yeah, i just do the same thing like you do...
@tanriol thankyou
i thought a reference is like a something pointer, i just point to the memory address. no matter how many references
i thought i know something about reference,but i'm confused now...
so why can't i store the reference into data the request owns?
Lyle Mantooth
@IslandUsurper
Nov 08 2018 14:14
@aohan237 , a reference is basically a pointer, but the compiler makes sure that it always points to something valid (in safe code). It doesn't allow them to exist whenever there's a mut reference to the same thing, because whatever has the mut reference can make changes that are unexpected to whatever holds the immutable reference(s). For the same reason, it doesn't allow two mutable references to something exist at the same time.
All that to say, if you want to use mutable references and immutable references, you have to be careful to show to the compiler that they don't exist at the same time.
However, you can pass a &mut T to any function that accepts a &T.
Hmmm. . . now I'm not sure that last statement is correct.
aohan237
@aohan237
Nov 08 2018 14:21
@IslandUsurper thanks, the last statement i will check it ...
but, in my example, the unmut borrow happens first, and then get the mut borrow
Lyle Mantooth
@IslandUsurper
Nov 08 2018 14:23
Order doesn't matter. You can't have both at the same time.
Zakarum
@omni-viral
Nov 08 2018 14:23
The reference has layout of the pointer. But there is a difference.
aohan237
@aohan237
Nov 08 2018 14:24
order is time?right? how to understand this same time?
in the same scope ,you must run first and then second
Lyle Mantooth
@IslandUsurper
Nov 08 2018 14:25
They can't exist in the same scope, basically.
aohan237
@aohan237
Nov 08 2018 14:25
@omni-viral what's the difference
yeah...if you say so..
but why? really confused...
Lyle Mantooth
@IslandUsurper
Nov 08 2018 14:25
Until we get NLL, though. That would change things.
aohan237
@aohan237
Nov 08 2018 14:26
NLL ? can you give me some links about it?
Lyle Mantooth
@IslandUsurper
Nov 08 2018 14:27
aohan237
@aohan237
Nov 08 2018 14:28
i have read the book several times... maybe still cant understand it,i will read it again. thank you
Zakarum
@omni-viral
Nov 08 2018 14:30
@aohan237 main difference - always valid
To ensure that they are has lifetime that doesn't let you to move them out of their scope
And ofc mutable reference is exclusive.
Lyle Mantooth
@IslandUsurper
Nov 08 2018 14:32
But NLL means non-lexical lifetimes. Currently, values and references are considered alive by the borrow checker until the end of a scope, and then they are dropped. This keeps you from making multiple mutable references, etc., within any particular scope. NLL is a new borrow checker that looks deeper and looks for the last time a reference is actually used, and ends the lifetime there (I'm sure this is a vast oversimplification). So the lifetime rules are still respected, but you can't just look at the lexical structure (scopes) to figure out where lifetimes are.
aohan237
@aohan237
Nov 08 2018 14:38
@omni-viral always valid? who? mut borrow or unmut borrow ? you mean unmut borrow has a life time that ensure you dont move them out of scope?
but every borrow has a lifetime? right?
Denis Lisov
@tanriol
Nov 08 2018 14:39
@aohan237 A reference is something like a pointer, but the compiler specifically checks that every reference lives no longer than what it references. If it cannot prove that, it returns an error.
aohan237
@aohan237
Nov 08 2018 14:40
if you make an unmut borrow then make an mut borrow , both reference live no longer than what it reference, right?
Denis Lisov
@tanriol
Nov 08 2018 14:42
And it also checks that something borrowed immutably cannot be borrowed mutably or accessed directly at the same time, or something borrowed mutably cannot be borrowed immutably.
aohan237
@aohan237
Nov 08 2018 14:42
@IslandUsurper ok,you mean this is the borrow checker's limit? if we have NLL, this will be no problem?
@tanriol i see your guys' conclusion both point to the borrow checker...
Lyle Mantooth
@IslandUsurper
Nov 08 2018 14:44
No, the same rules still apply. You can not have an immutable reference and a mutable reference to the same thing at the same time. NLL just changes what the borrow checker thinks "same time" means to be only as long as needed, instead of to the end of the scope.
Denis Lisov
@tanriol
Nov 08 2018 14:44
The problem is that if you could first pass the immutable borrow to something that expects it to be, well, immutable, and then take a mutable reference and modify it sneakily, everything would blow up.
aohan237
@aohan237
Nov 08 2018 14:45
@tanriol ok
yeah
that's problem.
thank you all~
it really helps
@IslandUsurper
Denis Lisov
@tanriol
Nov 08 2018 14:46
While there's a reference returned by req.uri().path(), you must not be able to do *req.uri_mut() = something_else; to avoid problems, and thus you cannot modify the request while keeping that reference.
aohan237
@aohan237
Nov 08 2018 14:46
@omni-viral
yeah, i think i know the trick...
now ..
because of your help
pub fn handle_url<'a>(
    &self,
    req: Request<Body>,
) -> Box<Future<Item = Response<Body>, Error = hyper::Error> + Send> {
    req.extensions_mut();
here is another question...
hope you dont think i'm annoying...
i now owned the req

cannot borrow immutable argument req as mutable

cannot borrow mutably
router.rs(23, 9): cannot borrow mutably

here is the snippet
i own the req but i can use this method?
i have to do this
let mut req =req
Denis Lisov
@tanriol
Nov 08 2018 14:51
mut req: Request<Body>,
aohan237
@aohan237
Nov 08 2018 14:51
to make req mut?
ok...
....
forgive me ...
Denis Lisov
@tanriol
Nov 08 2018 14:58
Asking questions is ok, no problems with that :-)
aohan237
@aohan237
Nov 08 2018 15:37
another one, which one is the best web frame work...which one should i choose?
or the top 5 framework
Ichoran
@Ichoran
Nov 08 2018 16:08
I find actix-web the best framework for me personally. If for some reason it doesn't suit you, you'll just have to try the others and find one that fits you and/or your requirements better.
If you just Google "rust web framework" you'll find a few blogs etc. that compare at least a few of them.
Ichoran
@Ichoran
Nov 08 2018 16:18
(There's enough to say about each of them that it really does take a blog, not something someone's likely to type out here.)
aohan237
@aohan237
Nov 08 2018 16:22
thank you ...
Ximo Guanter
@edrevo
Nov 08 2018 17:25

Hi everyone! I'm starting to play around with rust, and I've bumped into an error I am not able to work around... and it is such a simple piece of code!

    let mut fields2: HashMap<String, Vec<String>> = HashMap::new();
    match fields2.get_mut("temp") {
      Some(mut vec) => vec.push("dummy".to_string()),
      None => { fields2.insert("temp".to_string(), vec!("dummy".to_string())); }
    }

the compiler error I get is:

error[E0499]: cannot borrow `fields2` as mutable more than once at a time
  --> src\main.rs:81:17
   |
79 |     match fields2.get_mut("temp") {
   |           ------- first mutable borrow occurs here
80 |       Some(mut vec) => vec.push("dummy".to_string()),
81 |       None => { fields2.insert("temp".to_string(), vec!("dummy".to_string())); }
   |                 ^^^^^^^ second mutable borrow occurs here
82 |     }
   |     - first borrow ends here

how can I force the first borrow to finish before the insert?

Lyle Mantooth
@IslandUsurper
Nov 08 2018 17:45
@edrevo, sounds like the problem the Entry API is designed to solve.
Ximo Guanter
@edrevo
Nov 08 2018 17:46
great! thanks for the pointers!
Chuck Musser
@cmusser
Nov 08 2018 20:00

I've created an iterable set of futures, but can't make it resilient in the case where an operation in a map() fails.

In the function below, the call to Name::from_str could return an Err variant. get_future() returns impl Future<Item=String, Error=String>

let futures = list.map(|item| get_future(Name::from_str(item).unwrap()));

I attempted to ignore the from_str failure by matching them and creating an "ok" future, but ran into a type problem I don't understand.

This is the code:

let futures = nameservers.map(|itme| {
    match Name::from_str(item) {
        Ok(name) => get_future(name),
        Err(e) => futures::future::ok(String::from(e)),
    }
});

I don't understand the resulting error:

error[E0308]: match arms have incompatible types
  --> src/main.rs:96:13
   |
96 | /             match Name::from_str(ns) {
97 | |                 Ok(name) => get_future(name),
98 | |                 Err(e) => futures::future::ok(String::from(e)),
   | |                           ------------------------------------ match arm with an incompatible type
99 | |             }
   | |_____________^ expected opaque type, found struct `futures::FutureResult`
   |
   = note: expected type `impl futures::Future`
              found type `futures::FutureResult<std::string::String, _>`

How can I create a set of futures that perform the task if the name could be created or simply return the error text in the case of failure?

Ichoran
@Ichoran
Nov 08 2018 20:24
I think the problem is that it can't infer the type of the second argument. Try ok::<String, String>(...).
It does look like that error message could be significantly improved, though.
Chuck Musser
@cmusser
Nov 08 2018 20:29
hm, similar error about incompatible types. I wonder if there's something significantly different about the futures::FutureResult that isn't compatible. It says this now after changing it to futures::future::ok::<String, String>(String::from(e)),:
 = note: expected type `impl futures::Future`
              found type `futures::FutureResult<std::string::String, std::string::String>`
Ichoran
@Ichoran
Nov 08 2018 20:40
Huh. Dunno, sorry! If I were working it out, I'd write a function fn to_impl_future(in: impl Future<String, String>) -> impl Future<Item=String, Error=String> { in } and see what happens when you try to pass futures::future::ok... in to that.
Maybe the error message will be more informative.
Also, you have in your own code fixed the |itme| vs. item thing, right?
Chuck Musser
@cmusser
Nov 08 2018 20:43
heh, yeah, I do. I tried to write a function with the same return value as get_future and simply returned a futures:future::ok(). That yielded the same error as above, so I didn't learn anything there. Let me try passing the future in, like you say though.
red75prime
@red75prime
Nov 08 2018 20:44
fn to_impl_future(in: impl Future<String, String>) -> impl Future<Item=String, Error=String> { in } is the same as fn to_impl_future<F: Future>(in: F) -> SomeConcreteTypeImplementingFuture. The only implementation is { Box::new(in) as Box<Future<...>> }
Ichoran
@Ichoran
Nov 08 2018 20:50
@red75prime - Wait, so the return impl Trait is not the same type as the argument impl Trait?
Chuck Musser
@cmusser
Nov 08 2018 20:51
having trouble getting a little sample function to compile.
Ichoran
@Ichoran
Nov 08 2018 20:56
@red75prime - They look the same to me. This compiles:
trait Foo<A> { fn value() -> A; }
fn id(foo: impl Foo<i32>) -> impl Foo<i32> { foo }
Chuck Musser
@cmusser
Nov 08 2018 21:16

I tried:

fn id(input: impl Future) -> impl Future { input }
...
match Name::from_str(ns) {
         Ok(name) => get_ns_txt_id_query_future(recursive, name),
         Err(e) => id(futures::future::ok::<String, String>(String::from(e))),
}

Different error:
`` error[E0308]: match arms have incompatible types --> src/main.rs:97:13 | 97 | / match Name::from_str(ns) { 98 | | Ok(name) => get_ns_txt_id_query_future(recursive, name), 99 | | Err(e) => id(futures::future::ok::<String, String>(String::from(e))), | | ---------------------------------------------------------- match arm with an incompatible type 100 | | } | |_____________^ expected opaque type, found a different opaque type | = note: expected typeimpl futures::Future(opaque type) found typeimpl futures::Future` (opaque type)

Sorry, that wasn't readable...
error[E0308]: match arms have incompatible types
   --> src/main.rs:97:13
    |
97  | /             match Name::from_str(ns) {
98  | |                 Ok(name) => get_ns_txt_id_query_future(recursive, name),
99  | |                 Err(e) => id(futures::future::ok::<String, String>(String::from(e))),
    | |                           ---------------------------------------------------------- match arm with an incompatible type
100 | |             }
    | |_____________^ expected opaque type, found a different opaque type
    |
    = note: expected type `impl futures::Future` (opaque type)
               found type `impl futures::Future` (opaque type)
Denis Lisov
@tanriol
Nov 08 2018 21:56
The problem here is that get_ns_txt_id_query_future returns some specific future type that's not FutureResult (or at least not known to be that).
You need to either wrap both arms with Either or box them as Box<dyn Future<...>>
Yemi Bedu @ P&R
@pr-yemibedu
Nov 08 2018 21:58
@edrevo does it help to mark fields2 as ref fields2 inside the match so it does not try to make a new mut pointing to your HashMap?
Chuck Musser
@cmusser
Nov 08 2018 22:00
@tanriol : right, it returns impl Future<Item=String, Error=String>. That's what I was wondering earlier: if the impl Future... and FutureResult are not equivalent, is there something else I can use other than future::ok()? I'm not sure if I understand how to use Either, which seems an entirely different technique.
"it" meaning that get_ns_txt_id_query_futurefunction.
Denis Lisov
@tanriol
Nov 08 2018 22:34
They are not equivalent, but they implement the same interface. One option would be wrapping them with
match Name::from_str(ns) {
         Ok(name) => Either::A(get_ns_txt_id_query_future(recursive, name)),
         Err(e) => Either::B(futures::future::ok::<String, String>(String::from(e))),
}
Chuck Musser
@cmusser
Nov 08 2018 22:50
Well, OK that worked. Thanks! I'm curious about a few things. I thought implementing the same interface was equivalence, but clearly not. Why is that? Also, what does the Either() wrapper actually do here?
Denis Lisov
@tanriol
Nov 08 2018 23:05
Well, they are kinda equivalent on the high level, but not in detail. To unify them like in that match you need to have literally the same type. The Either wrapper wraps both of them into the same type Either<impl Future<...>, FutureResult<...>>. The other way of unifying them is to use dyn Future, but for that you need to box them (among other things, they can have different size, which is not ok without boxing or enum wrapping).
Chuck Musser
@cmusser
Nov 08 2018 23:10
Oh, ok. For the purpose of passing arguments or returning function values, it's sufficient to have "trait" equivalence, probably, but for things like the value of a match statement, the return values must literally be all of the same type. That does make sense. Seems like the purpose of Either is to relax this slightly.
Yemi Bedu @ P&R
@pr-yemibedu
Nov 08 2018 23:21

@edrevo i was stuck in not knowing how match captures the fields2 in a closure. so i made this in the playground

use std::collections::HashMap;

fn main() {
    let mut fields2: HashMap<String, Vec<String>> = HashMap::new();

    let has = fields2.get_mut("temp").map(|v| v.push("dummy".to_string()));

    if has.is_none()
    {
        fields2.insert("temp".to_string(), vec!("dummy".to_string()));
    }
}

fields2 using insert is lifted out of the scope and we also get to use nice map function to thread in our happy case.