Почему Rust хочет, чтобы размер Self был определен при реализации связанного const со связанным типом? - PullRequest
0 голосов
/ 29 июня 2018

Рассмотрим следующий код:

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 (CONST = 42). Негабаритные типы не должны реализовывать эту черту, поскольку impl<T> неявно предполагает T равным Sized.

Однако, когда я пытаюсь скомпилировать код , я получаю сообщение об ошибке:

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`

Мои вопросы:

  • Почему Руст считает, что T здесь не Sized? Явное указание T: Sized не помогает .
  • Давайте представим, что T не Sized. Почему Rust заботится о том, размер T здесь или нет? Насколько я могу судить, от этого ничего не зависит (связанный тип и const не связаны с T). Изменение кода на T: ?Sized работает, поэтому ясно, что T без размера на самом деле не проблема.

1 Ответ

0 голосов
/ 29 июня 2018

Согласно этой проблеме с GitHub , это, похоже, известная ошибка, возникшая по крайней мере начиная с 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 }
    }
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...