Hi
I have a problem which I suppose is caused by the higher rank trait bounds. It's the beginning of a debug console for an embedded system. The commands (CommandItem and MenuDef) would be defined statically and readonly. Each command has a function pointer, whose argument is a more volatile generic Context. This is passed in by reference at runtime.
My problem is that as soon as the context contains a reference, I'm getting a complaint that the context reference is too short lived and needs to be 'static
I'm pretty sure (from looking at similar posts, like Argument requires that ... is borrowed for `'static` ) that this is caused by the bounds on the function pointer, but cannot see how to fix it.
Any help would be appreciated!
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(dead_code)]
// #![deny(elided_lifetimes_in_paths)]
use std::marker::PhantomData;
type PhantomBound<'big, 'small> = PhantomData<&'small &'big ()>;
struct CommandItem<'a,'b,X> {
pub function: fn(ctx: &'b mut X),
pub name: &'a str
}
struct MenuDef<'a,'b,X> {
pub name: &'a str,
pub commands: &'a [&'a CommandItem<'a,'b,X>],
pub submenus: &'a [MenuDef<'a,'b,X>]
}
impl<'a,'b,X> MenuDef<'a,'b,X> {
pub fn run(self: &'a Self, text: &str, ctx: &'b mut X) -> Option<()> {
// ...
Option::Some(())
}
}
fn main() {
println!("Hello, world!");
}
#[cfg(test)]
mod tests {
use std::marker::PhantomData;
use crate::{CommandItem, MenuDef};
#[test]
fn test3() {
struct MenuContext<'a> {
stuff:&'a String
}
fn item1func(ctx: &mut MenuContext) {
println!("{}",ctx.stuff);
}
const ITEM1: CommandItem<MenuContext> = CommandItem {
function: item1func,
name: "Item1"
};
const MENU1: MenuDef<MenuContext> = MenuDef {
name: "root",
commands: &[&ITEM1],
submenus: &[]
};
let s1: String = "hello".into();
let mut c: MenuContext = MenuContext { stuff: &s1 };
assert_eq!(Option::Some(()),MENU1.run("Item1",&mut c));
assert_eq!(Option::None,MENU1.run("Item2", &mut c));
}
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0597]: `s1` does not live long enough
--> src/lib.rs:66:55
|
64 | let s1: String = "hello".into();
| -- binding `s1` declared here
65 |
66 | let mut c: MenuContext = MenuContext { stuff: &s1 };
| ^^^ borrowed value does not live long enough
67 | assert_eq!(Option::Some(()),MENU1.run("Item1",&mut c));
| ------------------------- argument requires that `s1` is borrowed for `'static`
68 | assert_eq!(Option::None,MENU1.run("Item2", &mut c));
69 | }
| - `s1` dropped here while still borrowed
error[E0597]: `c` does not live long enough
--> src/lib.rs:67:55
|
66 | let mut c: MenuContext = MenuContext { stuff: &s1 };
| ----- binding `c` declared here
67 | assert_eq!(Option::Some(()),MENU1.run("Item1",&mut c));
| ------------------^^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `c` is borrowed for `'static`
68 | assert_eq!(Option::None,MENU1.run("Item2", &mut c));
69 | }
| - `c` dropped here while still borrowed
error[E0499]: cannot borrow `c` as mutable more than once at a time
--> src/lib.rs:68:52
|
67 | assert_eq!(Option::Some(()),MENU1.run("Item1",&mut c));
| -------------------------
| | |
| | first mutable borrow occurs here
| argument requires that `c` is borrowed for `'static`
68 | assert_eq!(Option::None,MENU1.run("Item2", &mut c));
| ^^^^^^ second mutable borrow occurs here
Some errors have detailed explanations: E0499, E0597.
For more information about an error, try `rustc --explain E0499`.
error: could not compile `playground` (lib test) due to 3 previous errors
warning: build failed, waiting for other jobs to finish...