Rust: constインデックスの範囲外の状態を早期に報告する

作成日 2012年08月10日  ·  24コメント  ·  ソース: rust-lang/rust

現在、const exprでconstベクトルにインデックスを付けようとすると、コンパイルの後半で、変換中に境界オーバーランが報告されます。 const評価パスで、より早く気付くはずです。

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

最も参考になるコメント

ええ、私たちは6年後にこの問題を終えたと思います:笑い:

全てのコメント24件

明らかに、これによって生成される「エラー」によってコンパイルが失敗することはありません。コードが生成され、rustcは0を返します。インデックスが物理的に範囲外の場合はLLVMが文句を言います。これは現在、常に範囲外と同等です。インデックス(私は思う)ですが、constスライスの場合はそうではありません。

これはテスト中に特に予想外であり、(チェックファストを除いて、どうやら?)成功した​​場合の出力/エラーは表示されません。

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か月前)の例はまだ構文的に有効であり(yay!)、そのアサーションで失敗します(boo!)。

これは修正されたと思います。

@alexcrichtonの例を更新する場合:

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

fn main() {}

これで、文句なしに正常にコンパイルされます。

無効な値Bを使用しようとすると、 rustcで問題が発生します。

#![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

エラー:値で他の統計を参照できません。代わりにaddress-of演算子または定数を使用してください

うん、良さそうだ。

待ってください、 @ 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.

sooooはすでに後退しているようですか?

ええと、これは私の間違いでした。 LLVMアサーションを無効にしてコンパイルされたツールチェーンを使用して上記のレポートを作成しました(これがデフォルトであるとは知りませんでした)。

(こんにちは、私はE-easyの問題を初心者がより利用しやすいものにするのます:smile_cat :)

LLVMアサーションを無効にしてコンパイルされたツールチェーンを使用して上記のレポートを作成しました(これがデフォルトであるとは知りませんでした)。

この問題を再現するには、デフォルト以外の設定でコンパイルされたツールチェーンを使用する必要があるようです。 もしそうなら、どのようにそれを行うのですか?

ここで何が起こるのか混乱しているようで、すべての閉鎖と再開の作業が行われています。 誰かが期待される動作が何であるか、そしてそれが現在の動作とどのように異なるかを明確にすることができますか?

./configure --enable-llvm-assertions

ただし、LLVMアサーションが有効になっているため、Rustを毎晩使用できます。 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アサーションが無効になっていても、失敗ステータスで終了します(出力ファイルは書き込まれません)。 チェックが見逃したエラーを見つけることができるはずがなかったので、翻訳はチェックが行うセッション/エラーのものにアクセスできなかったと思いますか? しかし、今はそうではないようです。

私の過去の自己言及のもう1つのことは、範囲外であることがわかっていても、インデックスをLLVMに渡すだけだったように聞こえますが、代わりにundefを作成します。 ただし、エラーが適切に処理されるようになったため、どのような場合でもその部分は処理されます。

今日見ているLLVMアサーションについては、推測があります。 エラーを報告した後、これを実行しています。

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

そして、私たちはこのようなものが欲しいと思います(テストされていません):

C_undef(val_ty(arr).element_type())

インデックス付けされる値がスライスまたはポインターである場合、 bt (その型)は配列型で表されないため、 element_typeは失敗します。

しかし@ graydonがこの問題を開いたこと、およびこの問題を参照するコード内のコメントが実行を示唆していることは、そのチェックをコンパイルの初期段階に移動することです。 そして、#25370 /#25570は多かれ少なかれそれを達成することになるかもしれないように見えますか?

これは完全に修正されたと思います。 @ oli-obk?

いいえ、 check_constで解決する必要があり、現在のレポートの場所をバグの場所に変更する必要があります

@ oli-obkこれは簡単な修正ですか。もしそうなら、それを指導し、いくつかのヒントを残して、初心者がそれを試してみることができるようにしますか?

簡単な修正ですが(基本的にhttps://github.com/rust-lang/rust/blob/master/src/librustc/middle/check_const.rs#L470-L490を盗んで、 ExprIndex実行できますunimplemented!() )。

ただし、未使用のconst ARR: [u32; 0] = []; const X: u32 = ARR[5];現在コンパイルエラーを引き起こさないため、これは重大な変更にもなります。 また、 check_constは未使用の定数もチェックします。

また、すべてのconst評価を2回実行することになります。 定数をキャッシュすることで問題が発生すると、これを修正できます。

もちろん、重大な変更は、 const_errリントを放出するだけで修正できます。

これは、LLVMアサーションではなく、使用時にE0080をスローするようになったため、(おそらくMIRIが原因で)「解決」されたようです。 アクセスが使用されていない場合でも通過します。

constが使用されていないときに欠落しているlintは、 https://github.com/rust-lang/rust/pull/50110によって修正され

ええ、私たちは6年後にこの問題を終えたと思います:笑い:

このページは役に立ちましたか?
0 / 5 - 0 評価