Обновить
7
Владислав Белов@sick_hoof

Компиляторный инженер

27
Рейтинг
Отправить сообщение

В Rust действительно на какой-то стадии (честно, последний год не следил) есть концепция Tree Borrows. Но она ведь требует runtime поддержки и не является фундаментальным решеним для статических компиляторов. Мне вот покоя не давал этот пример

let mut root1 = 42;
let mut root2 = 43;
let mut ptr = &mut root1 as *mut i32;
let (x, mut y) = unsafe { (&mut *ptr, &mut *ptr) };
*x = 13;
ptr = &mut root2 as *mut i32;
y = unsafe {&mut *ptr };
*y = 20;
let val = *x + *y;

Я не являюсь экспертом языка rust, но насколько я понял, его разработчки попытались взять лучшее из подходов Fortran и C/C++, приправить safe/unsafe философией, где нужно, и в целом получили интересное решение. Является ли оно лучшим? Я думаю, что нет.

Отношения указателей, не указывающих в один storage - это UB.

Тут надо аккуратнее говорить, т.к здесь UB -- unspecified, не undefined. А так да, с этим есть определённого рода сложности

Давайте немного улучшим ваш пример, заменив assert на что-то более специфичное (когда мы хотим оптимизаций, мы assert'ы, как правило, выключаем). Для clang есть соответствующие builtin'ы:

int f(int x, int y) {

  __builtin_assume(x != y);

  *x = 42;
  *y = 14;

  return *x;
}

Внезапно, это ничего не даёт: ассемблер получится с всё тем же лишним релоадом. Связано это с особенностями работы alias analysis. Тем не менее, есть более тонкая настройка:

int f(int x, int y) {

  __builtin_assume_separate_storage(x, y);

  *x = 42;
  *y = 14;

  return *x;
}

И вот тут как раз-таки у компилятора развязываются руки

Тем не менее, стандартизация подобных вещей как раз-таки приводит нас к контрактному программированию и тому, о чём я рассказал, когда рассказывал disjoint

Информация

В рейтинге
316-й
Откуда
Москва, Москва и Московская обл., Россия
Работает в
Зарегистрирован
Активность

Специализация

Compiler developer
Средний
От 2 000 000 $
C++
C
Linux
Python
Git
Bash