Rust: Signaler plus tôt la condition hors limite de l'index de const

Créé le 10 août 2012  ·  24Commentaires  ·  Source: rust-lang/rust

Actuellement, si vous essayez d'indexer dans un vecteur const, dans une expr const, nous signalons le dépassement des limites en fin de compilation - pendant la traduction. Nous devrions le remarquer plus tôt, dans la passe d'évaluation const.

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

Commentaire le plus utile

Oui, je pense que nous en avons fini avec ce problème après 6 ans :rire:

Tous les 24 commentaires

Apparemment, "l'erreur" que cela produit ne provoque pas l'échec de la compilation - le code sera généré et rustc renverra 0. LLVM se plaindra si l'index est physiquement hors limites, et cela est actuellement toujours équivalent à un hors limites index (je pense), mais ce ne sera pas le cas pour les tranches const.

Ceci est particulièrement inattendu lors des tests, qui (sauf pour check-fast, apparemment ?) n'affichent pas la sortie/l'erreur en cas de succès.

Non critique pour 0,6 ; déphasage

Nomination pour le jalon 5, prêt pour la production

accepté pour le jalon prêt pour la production

A titre d'exemple de ce dont je pense qu'il s'agit :

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

fn main() {}

rendements

$ 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

Cela semble mauvais que nous ayons une assertion LLVM.

Accepté pour P-low.

Triage : l' exemple de

Je crois que c'est corrigé .

Si vous mettez à jour l'exemple de @alexcrichton :

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

fn main() {}

Il compile maintenant avec succès sans aucune plainte .

Ce n'est qu'une fois que vous essayez d'utiliser la valeur invalide B que rustc rencontrera un problème.

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

erreur : ne peut pas faire référence à d'autres statistiques par valeur, utilisez l'opérateur d'adresse de ou une constante à la place

Ouais, ça a l'air bien.

attendez, l'exemple de @JustAPerson ne me semble pas correct. Réouverture.

Je pense que c'est maintenant corrigé pour de vrai :

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

Donc, au cours des 11 derniers jours :

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.

tellement on dirait que c'est déjà régressé ?

Guh, c'était mon erreur. J'ai fait le rapport ci-dessus à l'aide d'une chaîne d'outils compilée avec les assertions LLVM désactivées (dont je ne savais pas qu'il s'agissait de la valeur par défaut).

(Bonjour, j'essaie d' aider à rendre les problèmes E-easy plus accessibles aux nouveaux arrivants :smile_cat :)

J'ai fait le rapport ci-dessus à l'aide d'une chaîne d'outils compilée avec les assertions LLVM désactivées (dont je ne savais pas qu'il s'agissait de la valeur par défaut).

Il semble que pour reproduire ce problème, vous devez utiliser une chaîne d'outils compilée avec un paramètre autre que celui par défaut ? Si oui, comment s'y prend-on ?

C'est un peu déroutant ce qui est censé se passer ici, avec tout ce qui se passe entre la fermeture et la réouverture. Quelqu'un pourrait-il préciser quel est le comportement attendu et en quoi il diffère du comportement actuel ?

./configure --enable-llvm-assertions

Cependant, vous pouvez simplement utiliser un Rust tous les soirs, car les assertions LLVM y sont activées. http://is.gd/X2RztV échoue toujours à l'assertion la nuit :

<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

Il semble que la chose qui m'inquiétait en 2013 soit corrigée : si rustc renvoie l'erreur const index-expr is out of bounds , même si les assertions LLVM sont désactivées, il sort avec un état d'échec (et n'écrit pas de fichier de sortie). Je pense que la traduction n'avait pas accès aux éléments de session/d'erreur que la vérification fait, car elle n'était pas censée être en mesure de trouver les erreurs que la vérification a manquées ? Mais il semble que ce ne soit plus le cas maintenant.

L'autre chose que mon passé a mentionnée… il semble que nous passions simplement l'index à LLVM même si nous savions qu'il était hors de portée, mais maintenant nous construisons un undef place. Mais cette partie est prise en charge dans tous les cas, car l'erreur est gérée correctement maintenant.

Quant à l'assertion LLVM que nous voyons aujourd'hui, j'ai une supposition. Après avoir signalé l'erreur, nous procédons comme suit :

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

et je pense que nous voulons quelque chose comme ça (non testé):

C_undef(val_ty(arr).element_type())

Parce que si la valeur indexée est une tranche ou un pointeur, alors bt (son type) ne sera pas représenté par un type de tableau, donc element_type échouera.

Mais , la chose pour laquelle

Je pense que c'est complètement corrigé maintenant. @oli-obk ?

non, il doit être résolu dans check_const et l'emplacement actuel du rapport doit être changé en un emplacement de bogue

@oli-obk Est-ce une solution facile, et si c'est le cas, voulez-vous l'encadrer et laisser quelques indices afin que les nouveaux arrivants puissent s'y essayer ?

Bien que ce soit une solution facile (vous pouvez essentiellement voler https://github.com/rust-lang/rust/blob/master/src/librustc/middle/check_const.rs#L470-L490 et le faire pour ExprIndex puis transformez https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/consts.rs#L708-L712 en un bug/ unimplemented!() ).

Mais ce serait aussi un changement radical, car les const ARR: [u32; 0] = []; const X: u32 = ARR[5]; inutilisés ne provoquent actuellement pas d'erreur de compilation. Et check_const vérifie également les constantes inutilisées.

De plus, cela finirait par faire toutes les évaluations const deux fois. Ce qui pourrait être résolu une fois que cela devient un problème en mettant en cache les constantes.

Bien sûr, le changement de rupture peut être corrigé en émettant simplement la peluche const_err .

cela semble avoir été «résolu» (peut-être à cause de MIRI) car il renvoie maintenant E0080 lorsqu'il est utilisé, plutôt qu'une assertion LLVM. bien qu'il passe encore si l'accès n'est pas utilisé.

Les peluches manquantes lorsque le const n'est pas utilisé seront corrigées par https://github.com/rust-lang/rust/pull/50110

Oui, je pense que nous en avons fini avec ce problème après 6 ans :rire:

Cette page vous a été utile?
0 / 5 - 0 notes