В настоящее время, если вы пытаетесь выполнить индексацию в вектор const, в выражении const мы сообщаем о превышении границ в конце компиляции - во время трансляции. Мы должны заметить это раньше, в проходе вычисления const.
Очевидно, «ошибка», которую это вызывает, не приводит к сбою компиляции - код будет сгенерирован, и 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 лет: смеется:
Самый полезный комментарий
Да, я думаю, что мы закончили с этой проблемой через 6 лет: смеется: