< 返回版块

Klad 发表于 2022-08-25 20:30

Tags:rust, trait, impl, tui-rs, tui

有这么一个函数:

pub fn new<B>() -> Result<Terminal<B>> {
    let backend = CrosstermBackend::new(io::stdout());
    Terminal::new(backend)
}

其中CrosstermBackend的大致定义:

pub struct CrosstermBackend<W: Write>;
impl<W> Backend for CrosstermBackend<W>
where W: Write {}

Terminal的定义:

pub struct Terminal<B>
where B: Backend {}

报错如下:

error[E0308]: mismatched types
   --> src/term.rs:13:19
    |
11  | pub fn new<B: Backend>() -> Result<Terminal<B>> {
    |            - this type parameter
12  |     let backend = CrosstermBackend::new(io::stdout());
13  |     Terminal::new(backend)
    |     ------------- ^^^^^^^ expected type parameter `B`, found struct `CrosstermBackend`
    |     |
    |     arguments to this function are incorrect
    |
    = note: expected type parameter `B`
                       found struct `CrosstermBackend<Stdout>`
note: associated function defined here
   --> /home/jedsek/.cargo/registry/src/mirrors.tuna.tsinghua.edu.cn-df7c3c540f42cdbd/tui-0.19.0/src/terminal.rs:175:12
    |
175 |     pub fn new(backend: B) -> io::Result<Terminal<B>> {
    |            ^^^

For more information about this error, try `rustc --explain E0308`.
error: could not compile `ncm-tui` due to previous error

但是换成impl后就可以了:

pub fn new() -> Result<Terminal<impl Backend>> {
    let backend = CrosstermBackend::new(io::stdout());
    Terminal::new(backend)
}

这是为什么?

评论区

写评论
作者 Klad 2022-08-25 22:01

rust论坛上有个答案:

strange for me

回答:

Self is the type being implemented, so it's Struct. The method Struct::new() takes a value of type T, which is a generic parameter, so whoever uses the type can choose it. So it doesn't make sense to call it with a value of type StructB – what if someone calls Struct::::a(), what should happen, then?

作者 Klad 2022-08-25 21:29

可为什么我把调用放在main函数就没有问题?

--
👇
7sDream: 因为你这个函数返回的确切类型只有一个,调用方无法通过 B 这个泛型参数来要求这个函数返回某个其他类型。

impl Trait 这个语法在参数位置的含义和在返回值位置里的含义不一样。在参数里的含义是你认为的这种泛型参数的简写;而在返回值里的含义其实是返回一个确定的,实现了某个 Trait 的匿名类型,而不是泛型。

详细可参阅TRPL 相关章节对应 RFC

7sDream 2022-08-25 21:08

因为你这个函数返回的确切类型只有一个,调用方无法通过 B 这个泛型参数来要求这个函数返回某个其他类型。

impl Trait 这个语法在参数位置的含义和在返回值位置里的含义不一样。在参数里的含义是你认为的这种泛型参数的简写;而在返回值里的含义其实是返回一个确定的,实现了某个 Trait 的匿名类型,而不是泛型。

详细可参阅TRPL 相关章节对应 RFC

1 共 3 条评论, 1 页