Rust: Informar la condición de fuera de límite de índice constante antes

Creado en 10 ago. 2012  ·  24Comentarios  ·  Fuente: rust-lang/rust

Actualmente, si intenta indexar en un vector constante, en una expr constante, informamos los límites sobrepasados ​​al final de la compilación, durante la traducción. Deberíamos notarlo antes, en el pase de evaluación constante.

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

Comentario más útil

Sí, creo que hemos terminado con este problema después de 6 años: riendo:

Todos 24 comentarios

Aparentemente, el "error" que esto produce no hace que la compilación falle; se generará código y rustc devolverá 0. LLVM se quejará si el índice está físicamente fuera de los límites, y esto actualmente es siempre equivalente a un fuera de los límites. index (creo), pero ese no será el caso de los cortes constantes.

Esto es especialmente inesperado durante la prueba, que (¿a excepción de la verificación rápida, aparentemente?) No muestra el resultado / error en caso de éxito.

No es crítico para 0.6; eliminación de millas

Nominado para el hito 5, listo para producción

aceptado para hito listo para producción

Como ejemplo de lo que creo que esto está hablando:

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

fn main() {}

rendimientos

$ 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

Parece malo que estemos alcanzando una afirmación LLVM.

Aceptado por P-bajo.

Triage: el ejemplo de

Creo que esto está arreglado .

Si actualiza el ejemplo de @alexcrichton :

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

fn main() {}

Ahora se compila con éxito sin quejas .

Solo una vez que intente utilizar el valor no válido B , rustc encontrará un problema.

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

error: no se puede hacer referencia a otras estáticas por valor, use el operador de dirección de o una constante en su lugar

Sí, parece bueno.

espera, el ejemplo de @JustAPerson no me parece bien. Reapertura.

Creo que esto ahora está arreglado de verdad:

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

Entonces, en algún momento de los últimos 11 días:

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.

¿Así que parece que ya ha retrocedido?

Guh, este fue mi error. Hice el informe anterior usando una cadena de herramientas compilada con las aserciones LLVM deshabilitadas (que no sabía que era la predeterminada).

(Hola, estoy tratando de ayudar a que los problemas de E-easy sean más accesibles para los recién llegados : smile_cat :)

Hice el informe anterior usando una cadena de herramientas compilada con las aserciones LLVM deshabilitadas (que no sabía que era la predeterminada).

Parece que para reproducir este problema, ¿debe usar una cadena de herramientas compilada con una configuración no predeterminada? Si es así, ¿cómo se hace?

Es un poco confuso lo que se supone que debe suceder aquí, con todas las cosas de cierre y reapertura que están sucediendo. ¿Alguien podría aclarar cuál es el comportamiento esperado y en qué se diferencia del comportamiento actual?

./configure --enable-llvm-assertions

Sin embargo, puede usar Rust todas las noches, ya que las afirmaciones LLVM están habilitadas allí. http://is.gd/X2RztV aún falla la afirmación en la noche:

<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

Parece que lo que me angustió en 2013 está arreglado: si rustc da el error const index-expr is out of bounds , incluso si las afirmaciones LLVM están deshabilitadas, sale con un estado de falla (y no escribe un archivo de salida). Creo que la traducción solía no tener acceso a las cosas de sesión / error que tiene la verificación, porque se suponía que no podía encontrar errores que la verificación no se pudo realizar. Pero parece que ese no es el caso ahora.

La otra cosa que mencioné en el pasado ... parece que solíamos pasar el índice a LLVM incluso si sabíamos que estaba fuera de rango, pero ahora construimos un undef lugar. Pero esa parte se soluciona en cualquier caso, porque el error se maneja correctamente ahora.

En cuanto a la afirmación de LLVM que estamos viendo hoy, supongo. Después de informar el error, estamos haciendo esto:

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

y creo que queremos algo como esto (no probado):

C_undef(val_ty(arr).element_type())

Porque si el valor que se indexa es un segmento o un puntero, bt (su tipo) no estará representado por un tipo de matriz, por lo que element_type fallará.

Pero , para lo que @graydon abrió este problema, y ​​lo que sugiere hacer el comentario en el código que hace referencia a este problema, es mover esa verificación a una etapa anterior de compilación. ¿Y parece que # 25370 / # 25570 podría terminar más o menos logrando eso?

Creo que esto está completamente arreglado ahora. @ oli-obk?

no, debe resolverse en check_const y la ubicación actual del informe debe cambiarse a una ubicación de error

@ oli-obk ¿Es esta una solución fácil y, de ser así, quieres ser un mentor y dejar algunas pistas para que los recién llegados puedan intentarlo?

Si bien es una solución fácil (básicamente puedes robar https://github.com/rust-lang/rust/blob/master/src/librustc/middle/check_const.rs#L470-L490 y hacerlo por ExprIndex y luego convertir https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/consts.rs#L708-L712 en un error / unimplemented!() ).

Pero también sería un cambio importante, porque el const ARR: [u32; 0] = []; const X: u32 = ARR[5]; no utilizado actualmente no causa un error de compilación. Y check_const también comprueba las constantes no utilizadas.

También terminaría haciendo todas las evaluaciones constantes dos veces. Lo cual podría remediarse una vez que se convierta en un problema almacenando en caché las constantes.

Por supuesto, el cambio importante se puede remediar simplemente emitiendo la pelusa const_err .

esto parece haber sido 'resuelto' (posiblemente debido a MIRI) ya que ahora arroja E0080 cuando se usa, en lugar de una aserción LLVM. aunque todavía pasa si el acceso no se utiliza.

Https://github.com/rust-lang/rust/pull/50110 solucionará la pelusa que falta cuando no se utiliza la constante.

Sí, creo que hemos terminado con este problema después de 6 años: riendo:

¿Fue útil esta página
0 / 5 - 0 calificaciones