У меня есть черта с некоторыми небольшими методами, которые обычно реализуются как однострочные обертки вокруг других методов, которые реализуют структуры. Если я хочу убедиться, что метод признака вложен, следует ли разместить #[inline(always)]
внутри определения признака или внутри impl
для каждой структуры? Я бы предпочел просто поместить его в определение признаков, но насколько я могу судить, это не работает.Может ли # [inline] использоваться как в декларациях и реализациях метода признаков?
ответ
Что означает inline
?
Когда компилятор строит вызов, он копирует тело функции на сайт вызова. По сути, это похоже на то, что код был скопирован/вставлен на каждый сайт вызова, где он встроен.
Что означает #[inline(always)]
?
Указывает, что компилятор всегда выполняет инкрустацию.
Обычно, компилятор выполняет подстановку, когда:
- тело функции, как известно
- множество эвристики считают, что это хороший компромисс (он не может быть, хотя), который в частности, зависит от размера тела функции
Почему я не могу указать #[inline(always)]
по методу признака?
Потому что нет тела.
Это может звучать банально, я знаю, однако это, тем не менее, правда.
В Руст, признаки могут быть использованы двумя способами:
- в пределах, для общих параметров
- , как во время выполнения интерфейсов, также известный как свойство объектов
При использовании в качестве объекта признака, в буквальном смысле нет тела: функция, которая будет называться, определяется во время выполнения!
Теперь существуют конкретные оптимизации (девиртуализации), где компилятор пытается угадать или отслеживать фактический динамический тип переменных, чтобы избежать динамической отправки. Я даже видел частичную девиртуализацию в GCC, где компилятор вычисляет вероятность каждого типа и создает лестницу if
для достаточно вероятного (if A { A::call(x); } else if B { B::call(x); } else { x.call(); }
). Конечно, это не гарантирует успех.
Итак, какова была бы семантика #[inline(always)]
по виртуальному звонку? Должен ли компилятор просто игнорировать атрибут молча (uh!)?
Мне кажется, что то, что вы ищете новый атрибут (require(inline(always))
?), Чтобы обеспечить соблюдение определенных ограничений на реализациях методов признака.
Насколько я знаю, этого еще не существует.
Педантично, '# [inline (always)]' only [** запрашивает ** компилятор для inline] (https://doc.rust-lang.org/reference.html#inline-attributes), компилятор свободен игнорировать его. – Shepmaster
@Shepmaster: Пока вы правы, я был бы очень разочарован, если компилятор проигнорировал запрос '# [inline (always)]'. '# [inline]' - это подсказка, и это нормально, но '# [inline (always)]' - это порядок; если это не так, даже невозможно проверить, выгодна ли вставка или нет! –
Вы помещаете его в объявление метода по признаку и видите, что оно не работает. Я не знаю, на какой вопрос вы ответили; похоже, вы уже поняли это. – Shepmaster