Родовые дженерики по функциям [дубликат]

Я столкнулся с этой проблемой на php 7.1, который поставляется с High Sierra (OS X 10.13.5), редактирование /etc/apache2/httpd.conf со следующими изменениями помогло:

  1. Раскомментировать эту строку
    LoadModule php7_module libexec/apache2/libphp7.so
    
  2. Вставить пасту в конце
    <IfModule php7_module>
        AddType application/x-httpd-php .php
        AddType application/x-httpd-php-source .phps
    
        <IfModule dir_module>
            DirectoryIndex index.html index.php
        </IfModule>
    </IfModule>
    
2
задан swizard 19 January 2015 в 17:44
поделиться

2 ответа

К сожалению, то, что вы хотите сделать, в Rust на данный момент невыразимо.

Подпись Read, которая на самом деле будет работать, выглядит следующим образом (в псевдо-ржавчине):

trait<'r> Read for Self<'r> {
    fn read<'a>(mem: &'a [u8]) -> Result<Self<'a>, String>;  // '
}

То есть, Self должен быть более высоким типом в своем параметре времени жизни. Это требует поддержки более высокосортных типов, что является очень желательной особенностью в сообществе Rust, но которая еще не реализована.

Проблема с исходной сигнатурой:

trait Read<'a> {
    fn read(mem: &'a [u8]) -> Result<Self, String>;
}

заключается в том, что 'a является параметром для характеристики. Если этот признак используется как привязка к значению:

fn compare_to_smth<'a, T>(value: &T) -> bool where T: PartialEq+Read<'a>

, это означает, что вызывающая сторона этой функции выбирает фактический параметр времени жизни. Например, вызывающий может выбрать 'static:

fn compare_to_smth<T>(value: &T) -> bool where T: PartialEq+Read<'static>

Однако функция использует &[u8], чье время жизни не 'static.

Фактически, этот конкретный пример может быть не совсем корректным из-за дисперсии (я думаю, для этой жизни было бы здорово 'static здесь, но дисперсия времени жизни сама по себе несколько запутанна, поэтому я не уверен), но, тем не менее, общая идея - это то же: для того, чтобы это работало, метод Read::read должен быть полиморфным в течение жизни его аргумента и результата, но вы еще не можете написать такую ​​подпись.

5
ответ дан Vladimir Matveev 21 August 2018 в 07:37
поделиться
  • 1
    Спасибо за ваш ответ! Может быть, вы можете помочь мне найти правильный способ реализовать мою идею в ржавчине, используя имеющиеся в настоящее время абстракции? – swizard 19 January 2015 в 18:56
  • 2
    К сожалению, я не думаю, что в настоящее время это возможно. Я также столкнулся с этим, когда попытался улучшить безопасность типов некоторых из моего кода (хотя мне нужны параметризованные связанные типы, а не Self). Я не мог найти пути вокруг него. – Vladimir Matveev 19 January 2015 в 19:02

Я думаю, что проблема может быть больше в сигнатуре compare_to_smth.

fn compare_to_smth<'a, T>(value: &'a T) // this implies a T: 'a bound
                       // because otherwise we would not be able to
                       // have a &'a T (references can't live longer
                       // than the thing they reference)

, но затем внутри функции, которую вы выполняете:

let smth_value: T = Read::read(mem).unwrap(); 
                                 // give me something of type T that
                                 // lives less than T

Я могу быть неправ, но я не думаю, что это зависит от того, как определяется Read и насколько сложна система типов в будущем, так как все, что вы пишете с правой стороны, не изменяет того факта, что вы ожидаете T на левой стороне (и T должен пережить 'a).

«Достаточно умный компилятор» мог бы видеть, что smth_value на самом деле не дольше 'a и что вы " это безопасно, но в целом это будет небезопасно. Я уверен, что использование небезопасной трансмутации в compare_to_smth полностью победит вашу цель, но для демонстрации это работает:

fn compare_to_smth<'a, T>(value: &'a T) -> bool
    where T: Read<'a> + PartialEq
{
    let mem: &[u8] = &[0x01, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37];
    let smth_value = <U8AndStr as Read>::read(mem).unwrap();
    let vl: &U8AndStr = unsafe{ std::mem::transmute(value) };

    smth_value == *vl
}
1
ответ дан Paolo Falabella 21 August 2018 в 07:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: