Rust: Informar a condição fora do limite do índice const mais cedo

Criado em 10 ago. 2012  ·  24Comentários  ·  Fonte: rust-lang/rust

Atualmente, se você tentar indexar em um vetor const, em uma expr const, relatamos a saturação de limites mais tarde na compilação - durante a tradução. Devemos notar isso antes, na passagem de avaliação const.

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

Comentários muito úteis

Sim, acho que acabamos com esse problema depois de 6 anos: rindo:

Todos 24 comentários

Aparentemente, o “erro” que isso produz não causa falha na compilação - o código será gerado e o rustc retornará 0. O LLVM reclamará se o índice estiver fisicamente fora dos limites, e isso atualmente é sempre equivalente a um fora dos limites index (eu acho), mas não será o caso para fatias const.

Isso é especialmente inesperado durante o teste, que (exceto para verificação rápida, aparentemente?) Não mostra a saída / erro em caso de sucesso.

Não crítico para 0,6; de-milestoning

Nomeação para o marco 5, pronto para produção

aceito para marco pronto para produção

Como um exemplo do que acredito estar falando:

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

fn main() {}

rendimentos

$ 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 ruim que estamos atingindo uma afirmação LLVM.

Aceito para P-baixo.

Triagem: o exemplo de @alexcrichton (9 meses de idade) ainda é sintaticamente válido (yay!) E ainda falha com essa afirmação (boo!).

Eu acredito que isso está consertado .

Se você atualizar o exemplo de @alexcrichton :

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

fn main() {}

Ele agora é compilado com sucesso sem quaisquer reclamações .

Apenas quando você tentar usar o valor inválido B , rustc encontrará um 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

erro: não pode se referir a outras estatísticas por valor, use o operador address-of ou uma constante em seu lugar

Sim, parece bom.

espere, o exemplo de @JustAPerson não parece bom para mim. Reabertura.

Acho que agora isso está corrigido de verdade:

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

Então, em algum momento nos últimos 11 dias:

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.

tããão parece que já regrediu?

Guh, esse foi meu erro. Eu fiz o relatório acima usando um conjunto de ferramentas compilado com asserções LLVM desabilitadas (que eu não sabia que era o padrão).

(Olá, estou tentando ajudar a tornar os problemas do E-easy mais acessíveis aos recém-chegados : smile_cat :)

Eu fiz o relatório acima usando um conjunto de ferramentas compilado com asserções LLVM desabilitadas (que eu não sabia que era o padrão).

Parece que, para reproduzir esse problema, você precisa usar um conjunto de ferramentas compilado com uma configuração não padrão. Em caso afirmativo, como fazer isso?

É meio confuso o que deveria acontecer aqui, com todas as coisas de fechamento e reabertura acontecendo. Alguém poderia esclarecer qual é o comportamento esperado e como ele difere do comportamento atual?

./configure --enable-llvm-assertions

No entanto, você pode apenas usar um Rust todas as noites, já que as asserções do LLVM estão habilitadas lá. http://is.gd/X2RztV ainda falha na declaração à noite:

<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 o que estava me incomodando em 2013 foi corrigido: se rustc der o erro const index-expr is out of bounds , mesmo se as asserções do LLVM estiverem desabilitadas, ele sai com um status de falha (e não grava um arquivo de saída). Eu acho que a tradução costumava não ter acesso às coisas de sessão / erro que a verificação tem, porque não era para ser capaz de encontrar erros que a verificação omitiu? Mas parece que não é o caso agora.

A outra coisa que meu próprio passado mencionou ... parece que costumávamos apenas passar o índice para o LLVM, mesmo sabendo que estava fora do intervalo, mas agora construímos um undef vez disso. Mas essa parte está resolvida em qualquer caso, porque o erro é tratado corretamente agora.

Quanto à afirmação do LLVM que estamos vendo hoje, tenho um palpite. Depois de relatar o erro, estamos fazendo o seguinte:

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

e acho que queremos algo assim (não testado):

C_undef(val_ty(arr).element_type())

Porque se o valor que está sendo indexado for um slice ou ponteiro, então bt (seu tipo) não será representado por um tipo de array, então element_type falhará.

Mas , @graydon abriu esse problema, e o que o comentário no código que faz referência a esse problema sugere fazer, é mover essa verificação para um estágio anterior de compilação. E parece que # 25370 / # 25570 pode acabar mais ou menos conseguindo isso?

Acho que isso está completamente consertado agora. @ oli-obk?

não, ele precisa ser resolvido em check_const e o local do relatório atual precisa ser alterado para um local de bug

@oli-obk Esta é uma solução fácil e, em caso afirmativo, você quer ser seu mentor e deixar algumas dicas para que os novatos possam tentar uma solução?

Embora seja uma solução fácil (você pode basicamente roubar https://github.com/rust-lang/rust/blob/master/src/librustc/middle/check_const.rs#L470-L490 e fazer isso por ExprIndex e, em seguida, transformar https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/consts.rs#L708-L712 em um bug / unimplemented!() ).

Mas também seria uma alteração importante, porque const ARR: [u32; 0] = []; const X: u32 = ARR[5]; não usados ​​atualmente não causa um erro de compilação. E check_const também verifica constantes não utilizadas.

Além disso, acabaria fazendo todas as avaliações const duas vezes. O que pode ser remediado quando se tornar um problema, armazenando constantes em cache.

É claro que a alteração significativa pode ser corrigida simplesmente emitindo o lint const_err .

isso parece ter sido 'resolvido' (possivelmente devido ao MIRI), pois agora gera E0080 quando usado, em vez de uma asserção LLVM. embora ele ainda passe se o acesso não for usado.

O lint ausente quando o const não é usado será corrigido por https://github.com/rust-lang/rust/pull/50110

Sim, acho que acabamos com esse problema depois de 6 anos: rindo:

Esta página foi útil?
0 / 5 - 0 avaliações