为什么在实现具有关联类型的关联const时,Rust为什么要对Self进行大小调整?

时间:2018-06-29 06:20:11

标签: rust

考虑以下代码:

pub trait Trait {
  type Type;
  const CONST: Self::Type;
}

impl<T> Trait for T {
  type Type = u8;
  const CONST: u8 = 42;
}

我对Rust的理解(不正确?)是,该代码应该起作用,并且所有Sized类型现在都应实现Trait并具有关联的类型(Type = u8)和const({ {1}})。未定大小的类型不应实现此特征,因为CONST = 42隐式假定impl<T>T

但是,当我尝试compile the code时,我收到错误消息:

Sized

我的问题:

  • 为什么Rust认为这里的error[E0277]: the size for value values of type `T` cannot be known at compilation time --> src/main.rs:8:3 | 8 | const CONST: u8 = 42; | ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types--sized> = help: consider adding a `where T: std::marker::Sized` bound = note: required because of the requirements on the impl of `Trait` for `T` 不是TExplicitly stating T: Sized doesn't help
  • 让我们假装Sized不是T。 Rust为何在这里关心Sized的大小?据我所知,没有什么依赖它(关联的类型和const与T无关)。将代码更改为T是可行的,因此很明显T: ?Sized的大小实际上并没有问题。

1 个答案:

答案 0 :(得分:2)

根据this GitHub issue,这似乎是至少自Rust 1.23(我怀疑更长)以来一直存在的已知错误。

目前尚不清楚是什么原因导致了该问题以及何时/是否可以解决。只有一个相当模糊的假设:

  

我不熟悉编译器的内部原理,但我的假设是,在常量表达式评估器中无法正确评估取决于类型参数的关联类型和常量。在这种情况下,它的关联类型不能很好地降低:const VAL: Self::T = 5;强制Rust在编译时进行一些奇特的计算类型以进行类型检查,但是这种计算的代码中有一个错误。

有几种方法可以解决此问题:

  1. 在特征中指定具体类型:

    pub trait Trait {
        // type Type;  // no longer used
        const CONST: u8;
    }
    
  2. T中退出Sized

    impl<T: ?Sized> Trait for T {
        type Type = u8;
        const CONST: u8 = 42;
    }
    
  3. 使用函数而不是常量(贷记到@PeterHall):

    pub trait Trait {
      type Type;
      fn const_val() -> Self::Type;
    }
    
    impl<T> Trait for T {
      type Type = u8;
      fn const_val() -> Self::Type { 42 }
    }