2017-01-19 6 views
1

У меня есть черта с некоторыми небольшими методами, которые обычно реализуются как однострочные обертки вокруг других методов, которые реализуют структуры. Если я хочу убедиться, что метод признака вложен, следует ли разместить #[inline(always)] внутри определения признака или внутри impl для каждой структуры? Я бы предпочел просто поместить его в определение признаков, но насколько я могу судить, это не работает.Может ли # [inline] использоваться как в декларациях и реализациях метода признаков?

+2

Вы помещаете его в объявление метода по признаку и видите, что оно не работает. Я не знаю, на какой вопрос вы ответили; похоже, вы уже поняли это. – Shepmaster

ответ

1

Что означает 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))?), Чтобы обеспечить соблюдение определенных ограничений на реализациях методов признака.

Насколько я знаю, этого еще не существует.

+0

Педантично, '# [inline (always)]' only [** запрашивает ** компилятор для inline] (https://doc.rust-lang.org/reference.html#inline-attributes), компилятор свободен игнорировать его. – Shepmaster

+0

@Shepmaster: Пока вы правы, я был бы очень разочарован, если компилятор проигнорировал запрос '# [inline (always)]'. '# [inline]' - это подсказка, и это нормально, но '# [inline (always)]' - это порядок; если это не так, даже невозможно проверить, выгодна ли вставка или нет! –