Rust: Out-of-bound-Bedingung für konstanten Index früher melden

Erstellt am 10. Aug. 2012  ·  24Kommentare  ·  Quelle: rust-lang/rust

Wenn Sie derzeit versuchen, in einen const-Vektor zu indizieren, melden wir in einem const-expr die Grenzüberschreitung spät bei der Kompilierung – während der Übersetzung. Wir sollten es früher im const-Auswertungspass bemerken.

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

Hilfreichster Kommentar

Ja, ich glaube, nach 6 Jahren sind wir mit diesem Problem fertig :lacht:

Alle 24 Kommentare

Anscheinend führt der dadurch erzeugte „Fehler“ nicht dazu, dass die Kompilierung fehlschlägt – Code wird generiert und rustc gibt 0 zurück. LLVM beschwert sich, wenn der Index physisch außerhalb der Grenzen liegt, und dies ist derzeit immer gleichbedeutend mit einer außerhalb der Grenzen index (glaube ich), aber das wird bei const-Slices nicht der Fall sein.

Dies ist insbesondere während des Tests unerwartet, der (außer bei Check-fast anscheinend?) die Ausgabe/den Fehler bei Erfolg nicht anzeigt.

Nicht kritisch für 0,6; De-Meilensteine ​​​​

Nominierung für Meilenstein 5, serienreif

für serienreifen Meilenstein akzeptiert

Als Beispiel für das, was meiner Meinung nach gemeint ist:

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

fn main() {}

ergibt

$ 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

Scheint schlecht, dass wir überhaupt auf eine LLVM-Behauptung treffen.

Akzeptiert für P-niedrig.

Triage: Das Beispiel von @alexcrichton (9 Monate alt) ist immer noch syntaktisch gültig (yay!) und schlägt immer noch mit dieser Behauptung fehl (boo!).

Ich glaube das ist behoben .

Wenn Sie das Beispiel von @alexcrichton aktualisieren:

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

fn main() {}

Es kompiliert jetzt erfolgreich ohne Beanstandungen .

Nur wenn Sie versuchen, den ungültigen Wert B wird rustc auf ein Problem stoßen.

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

Fehler: kann nicht nach Wert auf andere Statiken verweisen, verwenden Sie stattdessen den Adressoperator oder eine Konstante

Ja, scheint gut.

warte, das Beispiel von @JustAPerson scheint mir nicht in Ordnung zu sein. Wiedereröffnung.

Ich denke, das ist jetzt wirklich behoben:

$ 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)

Also irgendwann in den letzten 11 Tagen:

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 scheint es schon zurückgebildet zu sein?

Puh, das war mein Fehler. Ich habe den obigen Bericht mit einer Toolchain erstellt, die mit deaktivierten LLVM-Assertionen kompiliert wurde (von denen ich nicht wusste, dass sie der Standard sind).

(Hallo, ich versuche , E-easy-Probleme für Neulinge zugänglicher zu machen :smile_cat:)

Ich habe den obigen Bericht mit einer Toolchain erstellt, die mit deaktivierten LLVM-Assertionen kompiliert wurde (von denen ich nicht wusste, dass sie der Standard sind).

Es hört sich so an, als ob Sie, um dieses Problem zu reproduzieren, eine Toolchain verwenden müssen, die mit einer nicht standardmäßigen Einstellung kompiliert wurde? Wenn ja, wie macht man das?

Es ist irgendwie verwirrend, was hier passieren soll, mit all den Dingen, die geschlossen und wieder geöffnet werden. Könnte jemand erklären, was das erwartete Verhalten ist und wie es sich vom aktuellen Verhalten unterscheidet?

./configure --enable-llvm-assertions

Sie können jedoch nur nachts ein Rust verwenden, da dort LLVM-Assertionen aktiviert sind. http://is.gd/X2RztV scheitert immer noch die Behauptung auf nightly:

<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

Es sieht so aus, als ob das, was mich 2013 beunruhigte, behoben wurde: Wenn rustc den Fehler const index-expr is out of bounds ausgibt, wird es mit einem Fehlerstatus beendet, selbst wenn LLVM-Assertionen deaktiviert sind (und keine Ausgabedatei schreibt). Ich denke, die Übersetzung hatte früher keinen Zugriff auf das Sitzungs- / Fehlermaterial, das die Überprüfung ausführt, weil sie nicht in der Lage sein sollte, Fehler zu finden, die bei der Überprüfung ausgelassen wurden? Aber das scheint jetzt nicht der Fall zu sein.

Die andere Sache, die mein früheres Ich erwähnte ... es klingt, als hätten wir den Index früher einfach an LLVM übergeben, auch wenn wir wussten, dass er außerhalb des zulässigen Bereichs lag, aber jetzt konstruieren wir stattdessen ein undef . Aber dieser Teil ist auf jeden Fall erledigt, da der Fehler jetzt richtig behandelt wird.

Was die LLVM-Behauptung betrifft, die wir heute sehen, habe ich eine Vermutung. Nachdem wir den Fehler gemeldet haben, gehen wir wie folgt vor:

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

und ich denke, wir wollen so etwas (ungetestet):

C_undef(val_ty(arr).element_type())

Denn wenn der indizierte Wert ein Slice oder ein Zeiger ist, dann wird bt (sein Typ) nicht durch einen Array-Typ dargestellt, also element_type fehl.

Aber das , wofür @graydon dieses Problem geöffnet hat, und was der Kommentar im Code, der auf dieses Problem verweist, vorschlägt, ist, diese Überprüfung auf eine frühere Stufe der Kompilierung zu verschieben. Und es sieht so aus, als ob #25370/#25570 das mehr oder weniger erreichen könnten?

Ich denke das ist jetzt komplett behoben. @oli-obk ?

nein, es muss in check_const gelöst werden und der aktuelle Berichtspeicherort muss in einen Fehlerspeicherort geändert werden

@oli-obk Ist dies eine einfache Lösung, und wenn ja, möchten Sie es betreuen und einige Hinweise hinterlassen, damit Neulinge es ausprobieren können?

Obwohl es eine einfache Lösung ist (Sie können im Grunde https://github.com/rust-lang/rust/blob/master/src/librustc/middle/check_const.rs#L470-L490 stehlen und es für ExprIndex tun unimplemented!() ).

Aber es wäre auch eine bahnbrechende Änderung, da nicht verwendete const ARR: [u32; 0] = []; const X: u32 = ARR[5]; derzeit keinen Kompilierungsfehler verursachen. Und check_const überprüft auch nicht verwendete Konstanten.

Außerdem würde es am Ende alle const-Auswertungen zweimal durchführen. Was durch das Caching von Konstanten behoben werden könnte, sobald es zu einem Problem wird.

Natürlich kann der Breaking Change durch einfaches Ausgeben des const_err lint behoben werden.

dies scheint "gelöst" zu sein (möglicherweise aufgrund von MIRI), da es jetzt E0080 auslöst, wenn es verwendet wird, anstatt eine LLVM-Assertion. obwohl es immer noch durchläuft, wenn der Zugriff nicht verwendet wird.

Der fehlende Fussel, wenn die const nicht verwendet wird, wird von https://github.com/rust-lang/rust/pull/50110 . behoben

Ja, ich glaube, nach 6 Jahren sind wir mit diesem Problem fertig :lacht:

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen