Rust: Сообщить о выходе за пределы константного индекса ранее

Созданный на 10 авг. 2012  ·  24Комментарии  ·  Источник: rust-lang/rust

В настоящее время, если вы пытаетесь выполнить индексацию в вектор const, в выражении const мы сообщаем о превышении границ в конце компиляции - во время трансляции. Мы должны заметить это раньше, в проходе вычисления const.

A-diagnostics C-cleanup P-low T-compiler

Самый полезный комментарий

Да, я думаю, что мы закончили с этой проблемой через 6 лет: смеется:

Все 24 Комментарий

Очевидно, «ошибка», которую это вызывает, не приводит к сбою компиляции - код будет сгенерирован, и rustc вернет 0. LLVM будет жаловаться, если индекс физически выходит за пределы, и в настоящее время это всегда эквивалентно выходу за пределы index (я думаю), но для константных срезов это не так.

Это особенно неожиданно во время тестирования, которое (кроме быстрой проверки, по-видимому?) Не показывает результат / ошибку в случае успеха.

Не критично для 0.6; расчистка

Номинация на этап 5, готово к производству

принято к производству вехой

В качестве примера того, о чем я думаю, идет речь:

static a: &'static [int] = &[];
static b: int = a[1];

fn main() {}

дает

$ rustc foo.rs
foo.rs:2:16: 2:19 error: const index-expr is out of bounds
foo.rs:2 static b: int = a[1];
                         ^~~
Assertion failed: (ReqTy && "extractvalue indices invalid!"), function getExtractValue, file ../../../../src/llvm/lib/IR/Constants.cpp, line 1982.
zsh: abort      rustc foo.rs

Плохо, что мы вообще сталкиваемся с утверждением LLVM.

Принято для P-low.

Сортировка: пример @alexcrichton (9-месячной давности) все еще синтаксически действителен (ура!) И все еще терпит неудачу с этим утверждением (бум!).

Я считаю, что это исправлено .

Если вы обновите пример @alexcrichton :

#![allow(dead_code)]
const A: &'static [usize] = &[];
const B: usize = A[1];

fn main() {}

Теперь он успешно компилируется

rustc столкнется с проблемой только после того, как вы попытаетесь использовать недопустимое значение B .

#![allow(dead_code)]
const A: &'static [usize] = &[];
const B: usize = A[1];

fn main() {
    println!("B={}", B);
}
<anon>:3:18: 3:22 error: const index-expr is out of bounds
<anon>:3 const B: usize = A[1];
                          ^~~~
rustc: /home/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/llvm/lib/IR/Constants.cpp:2174: static llvm::Constant* llvm::ConstantExpr::getExtractValue(llvm::Constant*, llvm::ArrayRef<unsigned int>, llvm::Type*): Assertion `ReqTy && "extractvalue indices invalid!"' failed.
Aborted (core dumped)
playpen: application terminated with error code 134

ошибка: нельзя ссылаться на другие статики по значению, используйте вместо этого оператор адреса или константу

Ага, вроде хорошо.

подождите, пример @JustAPerson мне не подходит. Повторное открытие.

Я думаю, что теперь это исправлено по-настоящему:

$ cat foo.rs
#![allow(dead_code)]
const A: &'static [usize] = &[];
const B: usize = A[1];

fn main() {
    println!("B={}", B);
}
$ rustc foo.rs
foo.rs:3:18: 3:22 error: const index-expr is out of bounds
foo.rs:3 const B: usize = A[1];
                          ^~~~
error: aborting due to previous error
$ rustc --version
rustc 1.0.0-dev (a691f1eef 2015-04-15) (built 2015-04-15)

Итак, где-то за последние 11 дней:

hello.rs:3:18: 3:22 error: const index-expr is out of bounds
hello.rs:3 const B: usize = A[1];
                            ^~~~
rustc: /home/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/llvm/include/llvm/Support/Casting.h:237: typename llvm::cast_retty<X, Y*>::ret_type llvm::cast(Y*) [with X = llvm::SequentialType; Y = llvm::Type; typename llvm::cast_retty<X, Y*>::ret_type = llvm::SequentialType*]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.

таааак кажется, что это уже регресс?

Эх, это была моя ошибка. Я сделал приведенный выше отчет, используя набор инструментов, скомпилированный с отключенными утверждениями LLVM (которые, как я не знал, использовались по умолчанию).

(Привет, я пытаюсь сделать проблемы E-easy более доступными для новичков : smile_cat :)

Я сделал приведенный выше отчет, используя набор инструментов, скомпилированный с отключенными утверждениями LLVM (которые, как я не знал, использовались по умолчанию).

Похоже, чтобы воспроизвести эту проблему, вы должны использовать набор инструментов, скомпилированный с настройками, отличными от настроек по умолчанию? Если да, то как это сделать?

Это немного сбивает с толку, что здесь должно происходить, со всеми происходящими закрытием-открытием. Может ли кто-нибудь прояснить, что такое ожидаемое поведение и чем оно отличается от текущего поведения?

./configure --enable-llvm-assertions

Однако вы можете просто использовать Rust nightly, поскольку там включены утверждения LLVM. http://is.gd/X2RztV по- прежнему не выполняет утверждение по ночам:

<anon>:2:17: 2:21 error: const index-expr is out of bounds
<anon>:2 static b: i32 = a[1];
                         ^~~~
rustc: /home/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/llvm/include/llvm/Support/Casting.h:237: typename llvm::cast_retty<X, Y*>::ret_type llvm::cast(Y*) [with X = llvm::SequentialType; Y = llvm::Type; typename llvm::cast_retty<X, Y*>::ret_type = llvm::SequentialType*]: Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
Aborted (core dumped)
playpen: application terminated with error code 134

Похоже, что то, что меня огорчало в 2013 году, исправлено: если rustc выдает ошибку const index-expr is out of bounds , даже если утверждения LLVM отключены, он выходит со статусом сбоя (и не записывает выходной файл). Я думаю, что раньше у перевода не было доступа к сеансам / ошибкам, которые делает проверка, потому что он не должен был иметь возможность находить ошибки, пропущенные при проверке? Но похоже, что сейчас это не так.

Другая вещь, о которой упоминал мой прошлый я ... звучит так, как если бы мы просто передавали индекс в LLVM, даже если мы знали, что он выходит за пределы диапазона, но теперь мы вместо этого создаем undef . Но об этой части позаботятся в любом случае, потому что теперь ошибка обрабатывается правильно.

Что касается утверждения LLVM, которое мы наблюдаем сегодня, у меня есть предположение. Сообщив об ошибке, мы делаем следующее:

C_undef(type_of::type_of(cx, bt).element_type())

и я думаю, что мы хотим что-то вроде этого (непроверенного):

C_undef(val_ty(arr).element_type())

Поскольку, если индексируемое значение является срезом или указателем, тогда bt (его тип) не будет представлен типом массива, поэтому element_type завершится ошибкой.

Но то , для чего @graydon открыл эту проблему, и то, что предлагает сделать комментарий в коде,

Я думаю, что теперь это полностью исправлено. @ oli-obk?

нет, это нужно решить в check_const а текущее местоположение отчета необходимо изменить на местоположение ошибки

@ oli-obk. Это простое решение, и если да, не хотите ли вы наставлять его и оставлять подсказки, чтобы новички могли попробовать его?

Хотя это простое решение (вы можете просто украсть https://github.com/rust-lang/rust/blob/master/src/librustc/middle/check_const.rs#L470-L490 и сделать это за ExprIndex а затем превратите https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/consts.rs#L708-L712 в ошибку / unimplemented!() ).

Но это также было бы критическим изменением, потому что неиспользованный const ARR: [u32; 0] = []; const X: u32 = ARR[5]; настоящее время не вызывает ошибки компиляции. И check_const также проверяет неиспользуемые константы.

Кроме того, в конечном итоге все константные вычисления выполняются дважды. Что можно исправить, когда это станет проблемой, путем кэширования констант.

Конечно, критическое изменение можно исправить, просто выполнив команду const_err lint.

похоже, это было «решено» (возможно, из-за MIRI), поскольку теперь при использовании он выдает E0080 , а не утверждение LLVM. хотя он все еще проходит, если доступ не используется.

Отсутствие линта, когда константа не используется, будет исправлена https://github.com/rust-lang/rust/pull/50110

Да, я думаю, что мы закончили с этой проблемой через 6 лет: смеется:

Была ли эта страница полезной?
0 / 5 - 0 рейтинги