是否可以专注于静态寿命? [英] Is it possible to specialize on a static lifetime?

查看:57
本文介绍了是否可以专注于静态寿命?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想专门研究&'a str中的&'static str.像这样:

use std::borrow::Cow;

struct MyString {
    inner: Cow<'static, str>,
}

impl From<&'static str> for MyString {
    fn from(x: &'static str) -> Self {
        MyString {
            inner: Cow::Borrowed(x),
        }
    }
}

impl<T: Into<String>> From<T> for MyString {
    fn from(x: T) -> Self {
        MyString {
            inner: Cow::Owned(x.into()),
        }
    }
}

fn main() {
    match MyString::from("foo").inner {
        Cow::Borrowed(..) => (),
        _ => {
            panic!();
        }
    }

    let s = String::from("bar");
    match MyString::from(s.as_ref()).inner {
        Cow::Owned(..) => (),
        _ => {
            panic!();
        }
    }

    match MyString::from(String::from("qux")).inner {
        Cow::Owned(..) => (),
        _ => {
            panic!();
        }
    }
}

要点是MyString将静态分配的字符串文字存储为&'static str,并将所有其他字符串存储为String.这样,MyString可以避免使用生命周期参数(即MyString<'a>),这对我的API至关重要,同时允许调用者传递任何类型的字符串并让MyString自动执行正确的操作.

问题是代码无法编译:

 error[E0119]: conflicting implementations of trait `std::convert::From<&'static str>` for type `MyString`:
  --> src/main.rs:15:1
   |
7  | impl From<&'static str> for MyString {
   | ------------------------------------ first implementation here
...
15 | impl<T: Into<String>> From<T> for MyString {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyString`
 

有什么技巧可以让我做自己想做的事情吗?如果没有,Rust会支持终身专业化吗?

解决方案

Rust 1.25.0没有任何形式的专业化.如果我正在阅读正确地使用了专业化RFC ,那么即使实施了RFC,也将支持终生专业化:

特质系统设计中的一个硬约束是调度 不能依赖生命周期信息.特别是,我们俩都不能, 并且不应允许基于生命周期的专业化:

  • 我们不能,因为当编译器实际生成代码("trans")时,生存期信息已被删除-因此我们没有 弄清楚什么专业将适用.

  • 我们不应该这样做,因为生命周期推断是微妙的,通常会导致违反直觉的结果.例如,您很容易失败 即使'static也适用,因为推理是选择 与其他约束条件匹配的最小寿命.

(强调我的)

该链接中还有一些示例,指出了一些具体问题.

我建议使用Cow处理自有或借用"案件.

I want to specialize &'static str from &'a str. Something like this:

use std::borrow::Cow;

struct MyString {
    inner: Cow<'static, str>,
}

impl From<&'static str> for MyString {
    fn from(x: &'static str) -> Self {
        MyString {
            inner: Cow::Borrowed(x),
        }
    }
}

impl<T: Into<String>> From<T> for MyString {
    fn from(x: T) -> Self {
        MyString {
            inner: Cow::Owned(x.into()),
        }
    }
}

fn main() {
    match MyString::from("foo").inner {
        Cow::Borrowed(..) => (),
        _ => {
            panic!();
        }
    }

    let s = String::from("bar");
    match MyString::from(s.as_ref()).inner {
        Cow::Owned(..) => (),
        _ => {
            panic!();
        }
    }

    match MyString::from(String::from("qux")).inner {
        Cow::Owned(..) => (),
        _ => {
            panic!();
        }
    }
}

The gist is that MyString stores a statically-allocated string literal as a &'static str and all other strings as a String. This allows MyString to avoid having a lifetime parameter—i.e., MyString<'a>, which is critical for my API, all while allowing the caller to pass in any kind of string and have MyString automatically do the correct thing.

The problem is that the code doesn't compile:

error[E0119]: conflicting implementations of trait `std::convert::From<&'static str>` for type `MyString`:
  --> src/main.rs:15:1
   |
7  | impl From<&'static str> for MyString {
   | ------------------------------------ first implementation here
...
15 | impl<T: Into<String>> From<T> for MyString {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyString`

Is there any trick that allows me to do what I want? If not, is lifetime specialization something that Rust will ever support?

解决方案

Rust 1.25.0 does not have specialization of any kind. If I'm reading the specialization RFC correctly, then lifetime specialization will not be supported even when the RFC is implemented:

A hard constraint in the design of the trait system is that dispatch cannot depend on lifetime information. In particular, we both cannot, and should not allow specialization based on lifetimes:

  • We can't, because when the compiler goes to actually generate code ("trans"), lifetime information has been erased -- so we'd have no idea what specializations would soundly apply.

  • We shouldn't, because lifetime inference is subtle and would often lead to counterintuitive results. For example, you could easily fail to get 'static even if it applies, because inference is choosing the smallest lifetime that matches the other constraints.

(Emphasis mine)

There's some examples further in the link that indicate some of the concrete issues.

I recommend using a Cow to handle the "owned or borrowed" case.

这篇关于是否可以专注于静态寿命?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆