我在生命周期中遇到生锈编译错误

I am getting a rust compile error with lifetimes

我正在尝试编译一些 Rust 代码,但我不断收到有关类型和生命周期的错误。谁能解释我做错了什么?

我在编译时遇到错误:associated type bindings must be declared after generic parameters。我已经尝试过,我认为,参数的所有组合和它们的 none 似乎都有效。

这是我的代码的简化版本。

/*! test of lifetimes for compile */
extern crate web_view;
use web_view::*;
struct UserData {}

type TestResult = WVResult<i64>;
type TestView = WebView<UserData>;
type TestBuilder<'a> = WebViewBuilder< UserData: 'a,'a, 
         FnMut(&mut TestView, &str) -> TestResult, String>; // compile error

fn main() {
    let mut p = UserData {};
    let wvb: TestBuilder = WebViewBuilder::new();
    let mut webview: TestView = wvb
        .title("Progress")
        .content("hello")
        .size(640, 960)
        .resizable(true)
        .debug(false)
        .user_data(p)
        .invoke_handler(handler)
        .build()
        .unwrap();
    let _res = webview.run().unwrap();
}
fn handler(webview: &mut TestView, arg: &str) -> TestResult {
    Ok(1)
}

这应该是一条评论,但它太长了,无法放入评论中。我使用了@zizka 的答案,但恢复了我原来版本的 TestResult。现在我收到 "function or associated item not found" 和 "no method named title found for type"

的错误
use web_view::*;

struct UserData {}

type TestResult = WVResult<i64>;
type TestView<'a> = WebView<'a, UserData>;
type TestBuilder<'a> =
    WebViewBuilder<'a, UserData, fn(&mut TestView, &str) -> TestResult, &'static str>;

fn main() {
    let p = UserData {};

    let builder: TestBuilder = TestBuilder::new(); // error here
    let webview = builder
        .title("Progress") // error here
        .content(Content::Url("https://en.m.wikipedia.org/wiki/Main_Page"))
        .size(640, 960)
        .resizable(true)
        .debug(false)
        .user_data(p)
        .invoke_handler(handler)
        .build()
        .unwrap();
    webview.run().unwrap();
}

fn handler(_webview: &mut TestView, _arg: &str) -> TestResult {
    Ok(17 as i64)
}

问题

TestView

您的定义:

type TestView = WebView<UserData>;

WebView 定义为:

pub struct WebView<'a, T: 'a> {
    inner: *mut CWebView,
    _phantom: PhantomData<&'a mut T>,
}

它期望生命周期和 T,它必须与生命周期一样长。固定定义:

type TestView<'a> = WebView<'a, UserData>;

TestBuilder

您的定义:

type TestBuilder<'a> = WebViewBuilder< UserData: 'a,'a, 
         FnMut(&mut TestView, &str) -> TestResult, String>;

WebViewBuilder 定义为:

pub struct WebViewBuilder<'a, T: 'a, I, C>
    pub title: &'a str,
    pub content: Option<Content<C>>,
    pub width: i32,
    pub height: i32,
    pub resizable: bool,
    pub debug: bool,
    pub invoke_handler: Option<I>,
    pub user_data: Option<T>,
}
  • 'alifetime必须在前,你有在UserData
  • 之后
  • UserData 期望生命周期 -> UserData<'a>,而不是 UserData: 'a
  • FnMut(...)是一个trait,意思是编译时不知道大小,得用Box包起来,用fn,...
  • C 在您的情况下是 String,这意味着您不能使用 .content("hello"),因为 a) 它期望 Content<C>,b) 即使你使用 Content::Html("hello") 它不会起作用,因为它是 Content<&'static str> 而你说你想要 Content<String> -> Content::Html("hello".to_string())

固定定义:

type TestBuilder<'a> =
    WebViewBuilder<'a, UserData, Box<dyn FnMut(&mut TestView, &str) -> TestResult>, String>;

WebViewBuilder

但即使你解决了所有这些问题,它也不会奏效。查看 WebViewBuilder 实现:

impl<'a, T: 'a, I, C> Default for WebViewBuilder<'a, T, I, C>
where
    I: FnMut(&mut WebView<T>, &str) -> WVResult + 'a,
    C: AsRef<str>
{...}
impl<'a, T: 'a, I, C> WebViewBuilder<'a, T, I, C>
where
    I: FnMut(&mut WebView<T>, &str) -> WVResult + 'a,
    C: AsRef<str>,
{...}

尤其是这一行:

I: FnMut(&mut WebView<T>, &str) -> WVResult + 'a

它期望 WVResult (-> Result<(), Error>),这意味着你不能使用你的 TestResult (-> WVResult<i64> -> Result<i64, Error>).源代码中没有其他实现。

一个例子

工作代码,确实使用了您的类型,但 TestResult 只是 WVResulti64 -> ())。

use web_view::*;

struct UserData {}

type TestResult = WVResult;

type TestView<'a> = WebView<'a, UserData>;

type TestBuilder<'a> =
    WebViewBuilder<'a, UserData, Box<dyn FnMut(&mut TestView, &str) -> TestResult>, String>;

fn main() {
    let p = UserData {};

    let wvb: TestBuilder = WebViewBuilder::new();
    let webview: TestView = wvb
        .title("Progress")
        .content(Content::Url(
            "https://en.m.wikipedia.org/wiki/Main_Page".to_string(),
        ))
        .size(640, 960)
        .resizable(true)
        .debug(false)
        .user_data(p)
        .invoke_handler(Box::new(handler))
        .build()
        .unwrap();
    let _res = webview.run().unwrap();
}

fn handler(_webview: &mut TestView, _arg: &str) -> TestResult {
    Ok(())
}