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.
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:
Comentários muito úteis
Sim, acho que acabamos com esse problema depois de 6 anos: rindo: