Programmer in NYC

  • 0 Posts
  • 8 Comments
Joined 1 year ago
cake
Cake day: May 7th, 2023

help-circle






  • Well I’m curious to know what solutions there are to this. But I did reduce your problem to a smaller, self-contained example:

    struct ZKNoteStream<'a, T> {
        rec_iter: Box + 'a>,
    }
    
    struct BorrowedThing(Vec);
    
    impl BorrowedThing {
        fn prepare(&self) -> IterProducer<'_> {
            IterProducer(&self.0)
        }
    }
    
    struct IterProducer<'a>(&'a Vec);
    
    impl<'a> IterProducer<'a> {
        fn query_map(&self) -> impl Iterator {
            self.0.into_iter()
        }
    }
    
    fn test(conn: &BorrowedThing) -> ZKNoteStream<'_, &String> {
        let pstmt = conn.prepare();
        let rec_iter = pstmt.query_map();
    
        ZKNoteStream { // cannot return value referencing local variable `pstmt`
            rec_iter: Box::new(rec_iter),
        }
    }
    

    Edit: Wow, that code block came out mangled. Here is a Rust Playground link

    I ran into a similar problem yesterday, but it was a case where I had control over all the code. What I did was the equivalent of changing query_map so that instead of taking a reference to its receiver, it takes ownership.

    My thinking at the moment is that you may need to modify ZKNoteStream so that instead of containing the resulting iterator it contains pstmt, maybe paired with a function takes pstmt as an argument and returns the iterator. It seems like you should be able to create an FnOnce closure with a move keyword that moves ownership of pstmt into that closure, which you could then store in ZKNoteStream. But I’m not able to make that happen right now.


  • Taking a quick look at the changes, most of the changed code is in a block, not a function. I know the argument to Box::pin looks like a function, but it’s actually an async block. So you don’t have a function to return from.

    An anonymous function is introduced with an argument list surrounded by pipe characters (|) which you don’t have here. OTOH a block is introduced with curly braces. It is very common to use a block as the body of an anonymous function so it’s easy to mix those up.

    A block introduces a new variable scope. It can have keyword modifiers, async and move, as you have here. The entire block is a value which is determined by the last expression in the block.

    That’s a long way of saying: delete the return keyword, and remove the semicolon from the same line. That makes the value you want the last expression in the if body, which makes that become the value of the if expression, which then becomes the value of the block.