Rust: أبلغ عن حالة غير محددة لفهرس الثبات مسبقًا

تم إنشاؤها على ١٠ أغسطس ٢٠١٢  ·  24تعليقات  ·  مصدر: rust-lang/rust

حاليًا ، إذا حاولت الفهرسة في متجه ثابت ، في expr ، فإننا نبلغ عن تجاوز الحدود في وقت متأخر من التجميع - أثناء الترجمة. يجب أن نلاحظ ذلك مسبقًا ، في تمرير التقييم الثابت.

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

التعليق الأكثر فائدة

نعم أعتقد أننا انتهينا من هذه المشكلة بعد 6 سنوات: يضحك:

ال 24 كومينتر

من الواضح أن "الخطأ" الناتج عن هذا لا يتسبب في فشل التجميع - سيتم إنشاء الكود وسيعود rustc 0. سيشتكي LLVM إذا كان الفهرس خارج الحدود فعليًا ، وهذا دائمًا ما يعادل خارج الحدود index (على ما أظن) ، لكن هذا لن يكون هو الحال بالنسبة لشرائح const.

هذا غير متوقع بشكل خاص أثناء الاختبار ، والذي (باستثناء الفحص السريع ، على ما يبدو؟) لا يُظهر الإخراج / الخطأ عند النجاح.

ليست حرجة بالنسبة 0.6 ؛ دي ميلستون

الترشيح للمعلم 5 ، جاهز للإنتاج

تم قبولها للإنتاج الجاهز

كمثال على ما أعتقد أن هذا يتحدث عنه:

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

fn main() {}

عائدات

$ 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

يبدو سيئًا أننا نجري تأكيدًا على LLVM على الإطلاق.

مقبولة لـ P-low.

الفرز: مثالalexcrichton (عمره 9 أشهر) لا يزال ساريًا من الناحية التركيبية (رائع!) ولا يزال يفشل مع هذا التأكيد (بوو!).

أعتقد أن هذا تم إصلاحه .

إذا قمت بتحديث مثالalexcrichton :

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

fn main() {}

يتم تجميعها الآن بنجاح دون أي شكاوى .

بمجرد محاولة استخدام القيمة غير الصالحة B ستواجه rustc مشكلة.

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

خطأ: لا يمكن الإشارة إلى الإحصائيات الأخرى حسب القيمة ، استخدم عنوان عامل التشغيل أو ثابتًا بدلاً من ذلك

نعم ، يبدو جيدًا.

انتظر ، مثالJustAPerson لا يبدو جيدًا بالنسبة لي. إعادة الفتح.

أعتقد أن هذا تم إصلاحه الآن بشكل حقيقي:

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

لذلك ، في وقت ما خلال آخر 11 يومًا:

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 يبدو وكأنه قد تراجعت بالفعل؟

غوه ، كان هذا خطأي. لقد قدمت التقرير أعلاه باستخدام سلسلة أدوات تم تجميعها مع تعطيل تأكيدات LLVM (التي لم أكن أعرف أنها الإعداد الافتراضي).

(مرحبًا ، أحاول المساعدة في جعل المشكلات الإلكترونية سهلة الوصول إلى الوافدين الجدد : smile_cat :)

لقد قدمت التقرير أعلاه باستخدام سلسلة أدوات تم تجميعها مع تعطيل تأكيدات LLVM (التي لم أكن أعرف أنها الإعداد الافتراضي).

يبدو أنه من أجل إعادة إنتاج هذه المشكلة ، يجب أن تستخدم سلسلة أدوات تم تجميعها باستخدام إعداد غير افتراضي؟ إذا كان الأمر كذلك ، كيف يمكن للمرء أن يفعل ذلك؟

إنه نوع من الخلط بين ما يفترض أن يحدث هنا ، مع استمرار كل أمور إعادة الفتح. هل يمكن لأحد أن يوضح ما هو السلوك المتوقع وكيف يختلف عن السلوك الحالي؟

./configure --enable-llvm-assertions

ومع ذلك ، يمكنك فقط استخدام Rust ليلاً ، حيث يتم تمكين تأكيدات LLVM هناك. لا يزال http://is.gd/X2RztV يفشل في التأكيد ليلاً:

<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

يبدو أن الشيء الذي أزعجني في 2013 قد تم إصلاحه: إذا أعطى rustc الخطأ const index-expr is out of bounds ، حتى إذا تم تعطيل تأكيدات LLVM ، فإنه يخرج بحالة فشل (ولا يكتب ملف إخراج). أعتقد أن الترجمة لم تكن قادرة على الوصول إلى الجلسة / عناصر الأخطاء التي يتم التحقق منها ، لأنه لم يكن من المفترض أن تكون قادرة على العثور على أخطاء لم يتم التحقق منها؟ لكن يبدو أن الأمر ليس كذلك الآن.

الشيء الآخر الذي ذكرته نفسي في الماضي ... يبدو كما لو أننا اعتدنا تمرير الفهرس إلى LLVM حتى لو علمنا أنه خارج النطاق ، ولكننا الآن ننشئ undef بدلاً من ذلك. ولكن يتم الاهتمام بهذا الجزء على أي حال ، لأنه يتم التعامل مع الخطأ بشكل صحيح الآن.

بالنسبة لتأكيد LLVM الذي نراه اليوم ، لديّ تخمين. بعد الإبلاغ عن الخطأ ، نقوم بما يلي:

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

وأعتقد أننا نريد شيئًا كهذا (لم يتم اختباره):

C_undef(val_ty(arr).element_type())

لأنه إذا كانت القيمة التي يتم فهرستها عبارة عن شريحة أو مؤشر ، فلن يتم تمثيل bt (نوعه) بنوع مصفوفة ، لذلك سيفشل element_type .

لكن الشيء الذي فتح graydon له هذه المشكلة ، وما

أعتقد أن هذا تم إصلاحه تمامًا الآن. @ أولي obk؟

كلا ، يجب حلها في check_const ويجب تغيير موقع التقرير الحالي إلى موقع خطأ

@ oli-obk هل هذا حل سهل ، وإذا كان الأمر كذلك ، فهل تريد توجيهه وترك بعض التلميحات حتى يتمكن القادمون الجدد من محاولة حلها؟

في حين أنه حل سهل (يمكنك سرقة https://github.com/rust-lang/rust/blob/master/src/librustc/middle/check_const.rs#L470-L490 وقم بذلك مقابل ExprIndex ثم قم بتحويل https://github.com/rust-lang/rust/blob/master/src/librustc_trans/trans/consts.rs#L708-L712 إلى خطأ / unimplemented!() ).

ولكنه سيكون أيضًا تغييرًا مفاجئًا ، لأن const ARR: [u32; 0] = []; const X: u32 = ARR[5]; غير المستخدم حاليًا لا يتسبب في حدوث خطأ في التجميع. ويتحقق أيضًا check_const الثوابت غير المستخدمة.

كما سينتهي الأمر بإجراء جميع عمليات التقييم الثابتة مرتين. والتي يمكن معالجتها بمجرد أن تصبح مشكلة عن طريق التخزين المؤقت للثوابت.

بالطبع يمكن معالجة التغيير الكسر ببساطة عن طريق إصدار الوبر const_err .

يبدو أن هذا قد "تم حله" (ربما بسبب MIRI) لأنه يرمي الآن E0080 عند استخدامه ، بدلاً من تأكيد LLVM. على الرغم من أنه لا يزال يمر إذا كان الوصول غير مستخدم.

سيتم إصلاح الوبر المفقود عند عدم استخدام const من خلال https://github.com/rust-lang/rust/pull/50110

نعم أعتقد أننا انتهينا من هذه المشكلة بعد 6 سنوات: يضحك:

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات