error[E0502]: cannot borrow `nums` as immutable because it is also borrowed as mutable
--> src/main.rs:7:22
|
7 | foo(&mut nums[0..nums.len() - 1]);
| --------^^^^^^^^^^-----
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
| mutable borrow later used here
а такой проходит нормально
fn main() {
let mut nums = [1, 2, 3, 4, 5, 6, 7];
let last = nums.len() - 1;
foo(&mut nums[0..last]);
}
Мне казалось что первый код должен автоматом переходить во второй. Но получается диапазоны вносят какие-то модификации в этот алгоритм.
Есть ещё такой вариант, не знаю правда можно ли его рекомендовать. Не блещет элегантностью и split делает чуть больше чем тебе нужно.
Зато unwrap() тут честен. Если массив пустой, видно что выстрелит явно. С range-ами тоже выстрелит но из кода это видно не так явно.
Здравствуйте, johny5, Вы писали:
J>Есть ещё такой вариант, не знаю правда можно ли его рекомендовать. Не блещет элегантностью и split делает чуть больше чем тебе нужно.
интересный вариант. .1 только пугает. Не люблю такие конструкции. Это ж надо помнить, что там первый элемент, а что второй.
Да и вопрос был несколько в другом. Почему чекер здесь вообще ругается? Ответ вроде нашёл. Таки это "баг" компилятора, который ласково называют "ограничением". И учитывая, что живёт это давно, фиксить это никто не собирается.
Здравствуйте, sergii.p, Вы
> Почему чекер здесь вообще ругается? Ответ вроде нашёл. Таки это "баг" компилятора, который ласково называют "ограничением".
Странно я вроде дал тебе ответ что это не баг. Возражений не последовало. Но ты повторяешь свою претензию. Значит ты пришел поныть а не прлучить ответ. Держи минус
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
SP>интересный вариант. .1 только пугает. Не люблю такие конструкции. Это ж надо помнить, что там первый элемент, а что второй. SP>Да и вопрос был несколько в другом. Почему чекер здесь вообще ругается? Ответ вроде нашёл. Таки это "баг" компилятора, который ласково называют "ограничением". И учитывая, что живёт это давно, фиксить это никто не собирается.
Ну да, это неприятный момент в компиляторе. Ну нужно просто привыкнуть.
Здесь это неудобно, зато это часть большой доказательной машины на уровне компилятора отсутствия data racing в коде.
Такие "баги" иногда фиксят, для каких то вот подобных примитивных случаев добавляют в язык какие то новые пункты в правило. В данном случае, просто поменяв порядок получения ссылки можно было бы избежать ошибки компилятора. Можно предложить им в форум но у ребят там тяжёлая работа — язык должен не терять лаконичности и сильно переусложняться правилами. Но я был бы рад если такое получилось бы добавить — в данном случае изменение не хитрое.
Здравствуйте, T4r4sB, Вы писали:
TB>Странно я вроде дал тебе ответ что это не баг. Возражений не последовало. Но ты повторяешь свою претензию. Значит ты пришел поныть а не прлучить ответ. Держи минус
так вы же ничего не ответили. Вопрос был почему 1-ый код не компилируется, 2-ой — нормально. Хотя они идентичны. Зачем надо подставлять костыли в виде let, чтобы заставить корректный код работать? Ответ "Такой код запрещен", извините, для десткого сада.
Правильный ответ лежит в плоскости non-lexical lifetimes https://blog.rust-lang.org/2022/08/05/nll-by-default.html
То есть это реально ограничение borrow checker на данный момент.
Здравствуйте, sergii.p, Вы писали:
SP>споткнулся на такой забавный момент. Пока не понимаю причины SP>... SP>Мне казалось что первый код должен автоматом переходить во второй. Но получается диапазоны вносят какие-то модификации в этот алгоритм.
Здравствуйте, ArtDenis, Вы писали:
AD>Первый аргумент (&mut nums) функции IndexMut::index_mut уникально заимствует nums, поэтому во второй аргумент nums уже передать нельзя
Замечу ещё, что если бы self в расте передавался не первым аргументом функции, а последним, то код ТС компилировался без проблем
Здравствуйте, T4r4sB, Вы писали:
TB>Напомню что параметры для вызова функции всегда считаются слева направо. Это важно.
начал вас понимать, похоже. Только тут всё же немного не то. У нас один параметр в функции (и как раз не важно откуда считаются параметры). Только вызываем каскадно. Т.е.
let last = nums.len() - 1;
let slice = nums.index_mut(1..last);
foo(&mut slice);
и этот код вполне валиден. Короче, главный мой посыл: len вызывается до получения мутабельной ссылки, а не после. Нельзя получить slice без расчёта last.
Если бы было что-то вроде
foo(&mut nums, nums.len());
я бы даже согласился с такими доводами, хотя и то, не факт, что это мои проблемы разруливать здесь зависимости.
Здравствуйте, sergii.p, Вы писали:
SP>Здравствуйте, T4r4sB, Вы писали:
TB>>Напомню что параметры для вызова функции всегда считаются слева направо. Это важно.
SP>начал вас понимать, похоже. Только тут всё же немного не то. У нас один параметр в функции
Я не про функцию foo, а про функцию индексирования. У нее два параметра; ссылка на масств и число.
Как тут написалы выше, оператор [] это сахарок а на деле это вызов функции с двумя параметрами
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, ArtDenis, Вы писали:
AD>Здравствуйте, ArtDenis, Вы писали:
AD>>Первый аргумент (&mut nums) функции IndexMut::index_mut уникально заимствует nums, поэтому во второй аргумент nums уже передать нельзя
AD>Замечу ещё, что если бы self в расте передавался не первым аргументом функции, а последним, то код ТС компилировался без проблем
Вообще это жирный фейл, ведь паттерн
selm.mutable_method(self.smth)
довольно распространен.
Для него моглы бы и подправить борзочекер
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>Я не про функцию foo, а про функцию индексирования. У нее два параметра; ссылка на масств и число. TB>Как тут написалы выше, оператор [] это сахарок а на деле это вызов функции с двумя параметрами
да, ок, упустил из виду. Хотя из первого сообщения, согласитесь, это было не понять.