Rust: مشكلة في تتبع RFC 2342 ، "السماح بـ" if "و" المطابقة "في الثوابت"

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

هذه مشكلة تتبع لـ RFC "Allow if و match في الثوابت" (rust-lang / rfcs # 2342).

يرجى إعادة توجيه ضبط وظائف أو مشكلات معينة تريد الإبلاغ عنها إلى مشكلات جديدة وتسميتها بشكل مناسب بـ F-const_if_match حتى لا تغمر هذه المشكلات بالتعليقات سريعة الزوال التي تحجب التطورات المهمة.

خطوات:

أسئلة لم يتم حلها:

لا أحد

A-const-eval A-const-fn B-RFC-approved C-tracking-issue F-const_if_match T-lang disposition-merge finished-final-comment-period

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

الآن بعد أن تم دمج # 64470 و # 63812 ، فإن جميع الأدوات المطلوبة لهذا موجودة في المترجم. ما زلت بحاجة إلى إجراء بعض التغييرات على نظام الاستعلام حول تأهيل ثابت للتأكد من أنه ليس غير فعال دون داع مع تمكين هذه الميزة. نحن نحقق تقدمًا هنا ، وأعتقد أن تنفيذًا تجريبيًا لهذا سيكون متاحًا كل ليلة في أسابيع ، وليس أشهر (الكلمات الأخيرة الشهيرة: ابتسامة :).

ال 83 كومينتر

  1. إضافة ميزة بوابة لها
  2. تحتاج أدوات إنهاء switch و switchInt في https://github.com/rust-lang/rust/blob/master/src/librustc_mir/transform/qualify_consts.rs#L347 إلى وجود رمز مخصص في في حالة تنشيط بوابة الميزة
  3. بدلاً من وجود كتلة أساسية حالية واحدة (https://github.com/rust-lang/rust/blob/master/src/librustc_mir/transform/qualify_consts.rs#L328) يجب أن يكون هذا بعض الحاوية التي تحتوي على قائمة الكتل الأساسية التي لا يزال يتعين معالجتها.

@ oli-obk الأمر أكثر تعقيدًا بعض الشيء لأن تدفق التحكم المعقد يعني ضرورة استخدام تحليل تدفق البيانات. أحتاج إلى العودة إلى alexreg ومعرفة كيفية دمج تغييراتهم.

eddyb من المحتمل أن تكون نقطة البداية الجيدة هي أخذ فرعي const-qualif (مطروحًا منه أعلى الالتزام) ، وإعادة وضعه على المستوى الرئيسي (لن يكون ذلك ممتعًا) ، ثم إضافة عناصر التعليقات التوضيحية للبيانات ، أليس كذلك؟

أي أخبار عن هذا؟

@ مارك ايم للأسف لا. أعتقد أن eddyb كان مشغولاً للغاية بالفعل ، لأنني لم أتمكن حتى من

thread 'main' panicked at 'assertion failed: position <= slice.len()', libserialize/leb128.rs:97:1
note: Run with `RUST_BACKTRACE=1` for a backtrace.
error: Could not compile `rustc_llvm`.

Caused by:
  process didn't exit successfully: `/Users/alex/Software/rust/build/bootstrap/debug/rustc --crate-name build_script_build librustc_llvm/build.rs --error-format json --crate-type bin --emit=dep-info,link -C opt-level=2 -C metadata=74f2a810ad96be1d -C extra-filename=-74f2a810ad96be1d --out-dir /Users/alex/Software/rust/build/x86_64-apple-darwin/stage1-rustc/release/build/rustc_llvm-74f2a810ad96be1d -L dependency=/Users/alex/Software/rust/build/x86_64-apple-darwin/stage1-rustc/release/deps --extern build_helper=/Users/alex/Software/rust/build/x86_64-apple-darwin/stage1-rustc/release/deps/libbuild_helper-89aaac40d3077cd7.rlib --extern cc=/Users/alex/Software/rust/build/x86_64-apple-darwin/stage1-rustc/release/deps/libcc-ead7d4af4a69e776.rlib` (exit code: 101)
warning: build failed, waiting for other jobs to finish...
error: build failed
command did not execute successfully: "/Users/alex/Software/rust/build/x86_64-apple-darwin/stage0/bin/cargo" "build" "--target" "x86_64-apple-darwin" "-j" "8" "--release" "--manifest-path" "/Users/alex/Software/rust/src/librustc_trans/Cargo.toml" "--features" " jemalloc" "--message-format" "json"
expected success, got: exit code: 101
thread 'main' panicked at 'cargo must succeed', bootstrap/compile.rs:1085:9
note: Run with `RUST_BACKTRACE=1` for a backtrace.
failed to run: /Users/alex/Software/rust/build/bootstrap/debug/bootstrap -i build

حسنًا ، من المضحك بما فيه الكفاية ، أنني أعدت إقامتي مرة أخرى اليوم فقط ويبدو أن كل شيء على ما يرام الآن! يبدو أنه كان هناك انحدار ، وتم إصلاحه للتو. كل ذلك إلى eddyb الآن.

alexreg معذرةً ، لقد قمت بالتبديل إلى جدول نوم محلي وأرى أنك تضايقني عندما أستيقظ ولكن بعد ذلك تكون غير متصل طوال اليوم عندما أكون مستيقظًا (مناطق زمنية لاف).
هل يجب أن أقوم فقط بعمل علاقات عامة من فرعك؟ لقد نسيت ما كان من المفترض أن نفعل به؟

eddyb هذا ما يرام هيه. يجب أن تنام مبكرًا ، حيث إنني عادة ما أكون من الساعة 8:00 مساءً بتوقيت جرينتش ، لكن كل شيء على ما يرام! :-)

أنا آسف حقًا ، لقد استغرقت بعض الوقت لأدرك أن سلسلة التصحيحات المعنية تتطلب إزالة Qualif::STATIC{,_REF} ، أي الأخطاء المتعلقة بالوصول إلى الإحصائيات في وقت الترجمة. OTOH ، تم كسر هذا بالفعل من حيث const fn s والوصول إلى static s:

#![feature(const_fn)]
const fn read<T: Copy>(x: &T) -> T { *x }
static FOO: u32 = read(&BAR);
static BAR: u32 = 5;
fn main() {
    println!("{}", FOO);
}

لم يتم الكشف عن هذا بشكل ثابت ، وبدلاً من ذلك يشتكي miri من أنه "تم إلغاء الإشارة إلى المؤشر المتدلي" (والذي يجب أن يقول شيئًا عن static s بدلاً من "المؤشر المتدلي").

لذلك أعتقد أن قراءة static s في وقت الترجمة أمر جيد ، لكن بعض الناس يريدون أن يكون const fn "خالصًا" (أي "شفاف مرجعيًا" أو ما يقرب من ذلك) في وقت التشغيل ، مما يعني ذلك قراءة const fn من خلف مرجع حصلت عليه كوسيطة جيدة ، لكن const fn يجب ألا يكون قادرًا على الحصول على مرجع لـ static من فراغ (بما في ذلك من const s).

أعتقد أنه يمكننا الاستمرار في الإنكار الثابت لذكر static s (حتى لو أخذ مرجعهم فقط) في const s ، const fn ، وغيرها من السياقات الثابتة (بما في ذلك الترقيات).
ولكن لا يزال يتعين علينا إزالة الاختراق STATIC_REF والذي يسمح لـ static s بأخذ مرجع static s الأخرى ولكن (يحاول بشكل سيئ ويفشل) رفض القراءة من وراء تلك المراجع .

هل نحتاج إلى RFC من أجل هذا؟

يبدو نزيه قراءة كتابه من احصائيات. شك في أنه يحتاج إلى RFC ، ربما مجرد فوهة بركان ، لكن بعد ذلك ربما لست أفضل من أقوله.

لاحظ أننا لن نقيد أي شيء ، بل سنخفف من القيود التي تم كسرها بالفعل.

أوه ، لقد أخطأت في القراءة. هل سيظل تقييم الثبات سليماً ، لكن ليس شفافًا مرجعيًا؟

تصف الفقرة الأخيرة منهجًا مرجعيًا شفافًا (لكننا نفقد هذه الخاصية إذا بدأنا في السماح بذكر static s في const s و const fn s). لا أعتقد أن الصحة كانت قيد المناقشة حقًا.

حسنًا ، يبدو "المؤشر المتدلي" وكأنه مشكلة تتعلق بالسلامة ، لكنني أثق بك في هذا الأمر!

"المؤشر المتدلي" رسالة خطأ سيئة ، إنها مجرد ميري تمنع القراءة من static s. السياقات الثابتة الوحيدة التي يمكن أن تشير حتى إلى static s هي الأخرى static s ، لذلك يمكننا "فقط" السماح بهذه القراءات ، نظرًا لأن كل هذه التعليمات البرمجية تعمل دائمًا مرة واحدة ، في وقت الترجمة.

(من IRC) للتلخيص ، الشفافية المرجعية const fn يمكن أن تصل فقط إلى المخصصات المجمدة ، دون المرور بالوسيطات ، مما يعني أن const يحتاج إلى نفس القيد ، ويمكن أن تأتي التخصيصات غير المجمدة فقط من static s.

أحب الحفاظ على الشفافية المرجعية ، لذا تبدو فكرة eddyb رائعة!

نعم ، أنا مؤيد لأجعل const fns نقية أيضًا.

يرجى ملاحظة أن بعض الخطط التي تبدو غير ضارة يمكن أن تدمر الشفافية المرجعية ، على سبيل المثال:

let x = 0;
let non_deterministic = &x as *const _ as usize;
if non_deterministic.count_ones() % 2 == 0 {
    // do one thing
} else {
    // do a completely different thing
}

قد يفشل هذا مع وجود خطأ ميري في وقت الترجمة ، ولكنه سيكون غير حتمي في وقت التشغيل (لأننا لا نستطيع تمييز عنوان الذاكرة هذا على أنه "مجرد" مثل علبة ميري).

كانCentril فكرة جعل بعض العمليات المؤشر الخام (مثل المقارنات ويلقي إلى أعداد صحيحة): تحرير unsafe في const fn (الذي يمكننا القيام به حتى أننا الاستقرار const fn ) ، وذكر أنه لا يمكن استخدامها إلا بالطرق التي تسمح بها ميري في وقت الترجمة.
على سبيل المثال ، يجب أن يكون طرح مؤشرين إلى نفس المحلي أمرًا جيدًا (تحصل على مسافة نسبية تعتمد فقط على تخطيط النوع ومؤشرات المصفوفة وما إلى ذلك) ، ولكن تنسيق عنوان المرجع (عبر {:p} ) هو الاستخدام غير الصحيح، وبالتالي fmt::Pointer::fmt لا يمكن أن تكون علامة const fn .
أيضًا لا يمكن تمييز أي من السمات Ord / Eq للمؤشرات الأولية على أنها const (عندما نحصل على القدرة على التعليق عليها على هذا النحو) ، لأنها آمنة لكن العملية هي unsafe في const fn .

يعتمد على ما تقصده بكلمة "غير مؤذية" ... يمكنني بالتأكيد أن أرى سبب رغبتنا في حظر مثل هذا السلوك غير الحتمي.

سيكون رائعا إذا استمر العمل على هذا.

lachlansneff إنه يتحرك ... ليس بالسرعة التي نرغب فيها ، ولكن العمل https://github.com/rust-lang/rust/pull/51110 كمانع.

alexreg آه ، شكرا لك. سيكون من المفيد جدًا أن تكون قادرًا على تمييز تطابق أو إذا كان ثابتًا حتى عندما لا يكون في مجموعة ثابتة.

هل من تحديثات الحالة الآن بعد دمج # 51110؟

programmerjake أنا في انتظار بعض التعليقات من eddyb على https://github.com/rust-lang/rust/pull/52518 قبل أن يتم دمجها (نأمل قريبًا جدًا). لقد كان مشغولًا جدًا مؤخرًا (دائمًا ما يكون في ارتفاع الطلب) ، لكنه عاد إلى المراجعات وما إلى ذلك في الأيام القليلة الماضية ، لذلك أنا متفائل. بعد ذلك ، سيحتاج الأمر إلى بعض العمل من قبله شخصيًا ، كما أعتقد ، لأن إضافة تحليل تدفق البيانات المناسب أمر معقد. سنرى بالرغم من ذلك.

في مكان ما بقوائم TODO في المنشور (المنشورات) الأولى ، يجب إضافته لإزالة الاختراق الرهيب الحالي الذي يترجم && و || إلى & و | داخل الثوابت.

RalfJung ألم يكن هذا الجزء من تقييم const القديم ، الذي انتهى تمامًا الآن بعد أن أصبح MIRI CTFE في مكانه؟

AFAIK نقوم بهذه الترجمة في مكان ما في خفض HIR ، لأن لدينا رمزًا في const_qualify يرفض أدوات إنهاء SwitchInt التي كان من الممكن إنشاؤها بواسطة || / && .

أيضًا ، نقطة أخرى: قال @ oli-obk في مكان ما (لكن لا يمكنني العثور على مكان) أن الشروط الشرطية أكثر تعقيدًا إلى حد ما مما قد يعتقده المرء بسذاجة ...

هل كان ذلك "فقط" حول تحليل التغيّر الداخلي / المتساقط؟

أحاول حاليًا توضيح ذلك. سوف أعود إليكم عندما تكون لدي كل المعلومات

ما هي حالة هذا؟ هل هذا بحاجة إلى قوة بشرية أم أنه منع من حل مشكلة ما؟

@ mark-im تم حظره عند تنفيذ تحليل تدفق البيانات المناسب لتأهيل ثابت. eddyb هو الأكثر معرفة في هذا المجال ، وقد سبق له أن قام ببعض الأعمال في هذا المجال. (وأنا كذلك ، لكن هذا النوع من الركود ...) إذا لم يكن لدى eddyb الوقت ، فربما يمكن لـ @ oli-obk أو RalfJung معالجة هذا في وقت ما قريبًا. :-)

58403 هي خطوة صغيرة نحو التأهيل القائم على تدفق البيانات.

eddyb لقد ذكرت الحفاظ على الشفافية المرجعية في const fn ، والتي أعتقد أنها فكرة جيدة. ماذا لو منعت استخدام المؤشرات في const fn ؟ لذلك لن يتم تجميع نموذج الشفرة السابق الخاص بك بعد الآن:

let x = 0;
// compile time error: cannot cast reference to pointer in `const fun`
let non_deterministic = &x as *const _ as usize;
if non_deterministic.count_ones() % 2 == 0 {
    // do one thing
} else {
    // do a completely different thing
}

سيظل مسموحًا بالمراجع ولكن لن يُسمح لك باستبطانها:

let x = 0;
let p = &x;
if *p != 0 {  // this is fine
    // do one thing
} else {
    // do a completely different thing
}

اسمحوا لي أن أعرف إذا كنت خارج القاعدة تمامًا ، فقد اعتقدت أن هذه ستكون طريقة جيدة لجعل هذه الحتمية.

@ jyn514 التي يتم تغطيتها بالفعل من صنع كما usize يلقي غير مستقرة (https://github.com/rust-lang/rust/issues/51910)، ولكن يمكن للمستخدمين أيضا مقارنة المؤشرات الأولية (https://github.com/rust- lang / rust / issues / 53020) وهي سيئة بنفس القدر وبالتالي غير مستقرة أيضًا. يمكننا التعامل مع هذه بشكل مستقل عن التحكم في التدفق.

أي جديد على هذا؟

هناك بعض المناقشات حول https://rust-lang.zulipchat.com/#narrow/stream/146212 -t-compiler.2Fconst-Eval / topic / dataflow-based.20const.20qualification.20MVP

@ oli-obk الارتباط الخاص بك لا يعمل. ماذا يقول؟

إنه يعمل بالنسبة لي ... يجب عليك تسجيل الدخول إلى Zulip بالرغم من ذلك.

alexreg hmm نعم أفترض أنه كان alexreg هل تعرف سبب

إذا لم يكن لدينا إصدار قائم على تدفق البيانات ، فإننا إما نسمح عن طريق الخطأ &Cell<T> داخل الثوابت أو نمنع عن طريق الخطأ None::<&Cell<T>> (والذي يعمل على مستقر. من المستحيل بشكل أساسي التنفيذ بشكل صحيح بدون تدفق البيانات (أو أي تنفيذ سوف تكون نسخة مخصصة سيئة من تدفق البيانات)

@ est31 حسنًا ، @ oli-obk يفهم هذا بشكل أفضل مني ، ولكن من مستوى عالٍ بشكل أساسي ، فإن أي شيء يتضمن التفرع سوف يقوم بتقييم تدفق البيانات إلا إذا كنت تريد مجموعة من الحالات المتطورة. على أي حال ، يبدو أن هذا الشخص على Zulip يحاول العمل عليه ، وإذا لم أكن أعرف أن لدى oli-obk و eddyb نوايا لذلك ، ربما هذا الشهر أو التالي (منذ آخر مرة تحدثت معهم حول هذا الموضوع) ، على الرغم من أنني أستطيع لن يقدموا وعودًا نيابة عنهم.

alexreg @ mark-im @ est31 @ oli-obk يجب أن أكون قادرًا على نشر تطبيق ويب الخاص بي لمؤهلات إنشاء البيانات المستندة إلى تدفق البيانات في وقت ما من هذا الأسبوع. هناك الكثير من مخاطر التوافق هنا ، لذلك قد يستغرق الأمر بعض الوقت لدمجها بالفعل.

ممتاز؛ اتطلع اليه.

(نسخ من # 57563 لكل طلب)

هل يمكن وضع حالة خاصة bool && bool ، bool || bool ، إلخ؟ يمكن إجراؤها حاليًا const fn ، لكن القيام بذلك يتطلب عوامل تشغيل أحاديات ، وهو أمر غير مرغوب فيه في بعض الأحيان.

إنها بالفعل مغلفة بشكل خاص في عناصر const و static - عن طريق ترجمتها إلى عمليات البت. لكن هذا الغلاف الخاص يعد اختراقًا كبيرًا ومن الصعب جدًا التأكد من صحة ذلك بالفعل. كما قلت ، فهو أيضًا غير مرغوب فيه في بعض الأحيان. لذلك نحن نفضل عدم القيام بذلك في كثير من الأحيان.

سيستغرق القيام بالأشياء بشكل صحيح بعض الشيء ، لكنه سيحدث. إذا تراكمت لدينا الكثير من الاختراقات في هذه الأثناء ، فقد نؤلم أنفسنا في زاوية لا يمكننا الخروج منها (إذا انتهى الأمر ببعض هذه الاختراقات إلى التفاعل بطرق خاطئة ، وبالتالي استقرار السلوك عن طريق الخطأ الذي لا نريده).

الآن بعد أن تم دمج # 64470 و # 63812 ، فإن جميع الأدوات المطلوبة لهذا موجودة في المترجم. ما زلت بحاجة إلى إجراء بعض التغييرات على نظام الاستعلام حول تأهيل ثابت للتأكد من أنه ليس غير فعال دون داع مع تمكين هذه الميزة. نحن نحقق تقدمًا هنا ، وأعتقد أن تنفيذًا تجريبيًا لهذا سيكون متاحًا كل ليلة في أسابيع ، وليس أشهر (الكلمات الأخيرة الشهيرة: ابتسامة :).

@ نشوة مورس عظيم أن نسمع! نشكرك على جهودك المتضافرة لإنجاز ذلك ؛ أنا شخصياً كنت حريصًا على هذه الميزة منذ فترة حتى الآن.

أرغب في رؤية دعم تخصيص الكومة لـ CTFE بعد الانتهاء من ذلك. لا أعرف ما إذا كنت أنت أو أي شخص آخر مهتمًا بالعمل على هذا الأمر ، ولكن إذا لم يكن الأمر كذلك ، فربما يمكنني المساعدة.

alexreg شكرا!

انتهت المناقشة حول تخصيص الكومة في وقت التجميع في rust-rfcs / const-Eval # 20. AFAIK ، كانت أحدث التطورات حول نموذج ConstSafe / ConstRefSafe لتحديد ما يمكن ملاحظته مباشرة / خلف مرجع في القيمة النهائية const . أعتقد أن هناك حاجة إلى مزيد من أعمال التصميم بالرغم من ذلك.

بالنسبة لأولئك الذين يتابعون ذلك ، فإن # 65949 (الذي يعتمد في حد ذاته على عدد قليل من العلاقات العامة الأصغر) هو المانع التالي لذلك. على الرغم من أنه قد يبدو مرتبطًا بشكل عرضي ، إلا أن حقيقة أن التحقق من القيمة الثابتة / التأهيل كان مرتبطًا بإحكام بالترقية كان جزءًا من سبب حظر هذه الميزة لفترة طويلة. أخطط لفتح علاقات عامة لاحقة من شأنها إزالة المدقق القديم تمامًا (حاليًا نقوم بتشغيل كلا المدققين بالتوازي). سيؤدي هذا إلى تجنب أوجه القصور التي ذكرتها سابقًا.

بعد دمج كل من العلاقات العامة المذكورة أعلاه ، ستكون الثوابت if و match في الثوابت هي بعض التحسينات في التشخيص وعلامة ميزة بعيدًا! أوه ، وكذلك الاختبارات ، العديد من الاختبارات ...

إذا كنت بحاجة إلى اختبارات ، فأنا لست متأكدًا من كيفية البدء ولكني على أتم استعداد للمساهمة! فقط دعني أعرف أين يجب أن تذهب الاختبارات / كيف يجب أن تبدو / ما هو الفرع الذي يجب أن أسند إليه الرمز :)

العلاقات العامة التالية التي يجب مشاهدتها هي # 66385. يؤدي هذا إلى إزالة منطق تأهيل const القديم (الذي لا يمكنه معالجة التفريع) بالكامل لصالح الإصدار الجديد المستند إلى تدفق البيانات.

@ jyn514 سيكون ذلك رائعا! سأتواصل معك عندما أبدأ في صياغة التطبيق. سيكون من المفيد جدًا أيضًا أن يحاول الأشخاص انتهاك أمان ثابت (خاصةً الجزء HasMutInterior ) بمجرد توفر if و match كل ليلة.

يحتوي 66507 على تطبيق أولي لـ RFC 2342.

أتوقع أن الأمر سيستغرق بعض الوقت لإزالة الحواف الخشنة ، خاصة فيما يتعلق بالتشخيص ، وتغطية الاختبار متفرقة جدًا ( @ jyn514 يجب أن ننسق حول هذه المشكلة). ومع ذلك ، آمل أن نتمكن من إصدار هذا خلف علامة ميزة في الأسابيع القليلة المقبلة.

تم تنفيذ هذا في # 66507 ويمكن استخدامه الآن في آخر ليلة . هناك أيضًا منشور مدونة Inside Rust يوضح بالتفصيل العمليات المتاحة حديثًا بالإضافة إلى بعض المشكلات التي قد تواجهها مع التنفيذ الحالي حول الأنواع ذات القابلية للتغيير الداخلي أو الضماني Drop المخصص.

انطلق وداعب!

يبدو أن المساواة ليست const ؟ أم أنني مخطئ:

error[E0019]: constant function contains unimplemented expression type
  --> src/liballoc/raw_vec.rs:55:22
   |
55 |         let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0019]: constant function contains unimplemented expression type
  --> src/liballoc/raw_vec.rs:55:19
   |
55 |         let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

@ مارك- im يجب أن يعمل بالفعل . ربما مشكلة التمهيد؟ دعونا نناقش على Zulip.

لست متأكدًا مما إذا كان هذا مقصودًا ، ولكن محاولة المطابقة على تعداد يعطي الخطأ

الثابت fn مع رمز لا يمكن الوصول إليه غير مستقر

على الرغم من حقيقة أن التعداد شامل ومُعرّف في نفس الصندوق.

jhpratt هل يمكنك نشر الرمز؟ يمكنني المطابقة على تعدادات بسيطة بدون مشكلة: https://play.rust-lang.org/؟version=nightly&mode=debug&edition=2018&gist=585e9c2823afcb49c6682f69569c97ea

jhpratt هل يمكنك نشر الرمز؟ يمكنني المطابقة على تعدادات بسيطة بدون مشكلة:

هنا:
https://play.rust-lang.org/؟version=nightly&mode=debug&edition=2018&gist=13a9fbc4251d7db80f5d63b1dc35a98b

اضربني ببضع ثوان. هذا مثال بسيط يوضح حالتي بالضبط.

jhpratt بالتأكيد ليس مقصودًا. هل يمكنك فتح قضية؟

يرجى إعادة توجيه ضبط وظائف أو مشكلات معينة تريد الإبلاغ عنها إلى مشكلات جديدة وتسميتها بشكل مناسب بـ F-const_if_match حتى لا تغمر هذه المشكلات بالتعليقات سريعة الزوال التي تحجب التطورات المهمة.

Centril ليس شيئًا سيئًا أن تضعه في التعليق العلوي حتى لا يتم دفن تعليقك.

تحديث الحالة:

هذا جاهز للاستقرار من منظور التنفيذ ، ولكن هناك سؤال حول ما إذا كنا نريد الحفاظ على تدفق البيانات المستند إلى القيمة لدينا الآن بدلاً من النوع المستند إلى النوع (ولكن أقل قوة). يعد تدفق البيانات المستند إلى القيمة أغلى قليلاً (أكثر من ذلك في الأسفل) ، ونحن بحاجة إليه لوظائف مثل

const fn foo<T>() {
    let x = Option::<T>::None;
    {x};
}

التي قد يرفضها التحليل القائم على النوع ، لأن Option<T> قد يكون به مدمرات تحاول الآن تشغيلها وبالتالي قد تنفذ تعليمات برمجية غير ثابتة.

يمكننا الرجوع إلى التحليل القائم على النوع لحظة وجود الفروع ، ولكن هذا يعني أننا سنرفض

const fn foo<T>(b: bool) {
    let x = Option::<T>::None;
    assert!(b);
    {x};
}

الأمر الذي قد يكون مفاجئًا جدًا للمستخدمين.

قام @ ecstatic-morse بتشغيل التحليل على جميع الوظائف ، وليس فقط const fn وشهد تباطؤًا يصل إلى 5٪ (https://perf.rust-lang.org/compare.html؟ لاحظ أن هذا إصدار متشائم ، لأنه يعني أنه يتم تشغيله أيضًا على وظائف لن تصبح في كثير من الأحيان const fn .

هذا يعني أنه إذا أجرينا الكثير من الوظائف ثابتة ، فقد نشهد بعض التباطؤ في التجميع بسبب هذا التحليل القائم على القيمة.

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

أنا أرشح هذا لمناقشة @ rust-lang / lang حتى نتمكن من معرفة ما إذا كنا نريد المشاركة

  • الخيار القائم على النوع في وجود حلقات أو فروع (إعطاء سلوك غريب للمستخدمين)
  • التحليل القائم على القيمة الكاملة (أغلى ثمناً ، ولكن التعبير الكامل للمستخدمين)
  • مخطط مختلط ، لا يزال تعبيرًا كاملاً للمستخدمين ، بعض التعقيد الضمني الإضافي ، ولكن يجب تقليل مشاكل وقت الترجمة إلى الحالات التي تحتاجها.

@ أولي obk

الخيار القائم على النوع في وجود حلقات أو فروع (إعطاء سلوك غريب للمستخدمين)

فقط للتحقق من هذا: أليس خيارًا أن يكون لديك تحليل قائم على النوع حتى في كود مستقيم؟ أتخيل أن هذا نوع من التناقض للخلف ، نظرًا لأننا نقبل بالفعل ما يلي ( الملعب ):

struct Foo { }

impl Drop for Foo {
    fn drop(&mut self) { }
}

const T: Option<Foo> = None;

fn main() { }

أنا شخصياً أميل إلى التفكير في أننا يجب أن نضغط من أجل تجربة أفضل وأكثر اتساقًا للمستخدمين. يبدو أنه يمكننا التحسين حسب الحاجة ، وعلى أي حال التكلفة ليست سيئة للغاية. لكني أود أن أفهم بشكل أفضل قليلاً ما يحدث بالضبط في هذا التحليل الأكثر تكلفة: هي فكرة أننا نقوم في الأساس "بنشر مستمر" ، بحيث عندما يتم إسقاط شيء ما ، نقوم بتحليل القيمة الدقيقة التي يتم إسقاطها لتحديد ما إذا قد تحتوي على قيمة قد تحتاج إلى تشغيل أداة تدمير؟ (على سبيل المثال ، إذا كان None ، لاستخدام المثال الشائع Option<T> )

فقط للتحقق من هذا: أليس خيارًا أن يكون لديك تحليل قائم على النوع حتى في كود مستقيم؟ أتخيل أن هذا نوع من التناقض للخلف ، نظرًا لأننا نقبل بالفعل ما يلي (الملعب):

نعم ، هذا هو السبب في أننا لا نستطيع الانتقال بالكامل إلى التحليل القائم على النوع.

هي فكرة أننا نقوم بشكل أساسي بـ "انتشار مستمر" ، بحيث عندما يتم إسقاط شيء ما ، نقوم بتحليل القيمة الدقيقة التي يتم إسقاطها لتحديد ما إذا كانت تحتوي على قيمة قد تحتاج إلى تشغيل أداة تدمير؟ (على سبيل المثال ، إذا كان لا شيء ، فاستخدم المثال الشائع للخيار)

نحن ننشر فقط قائمة الأعلام ( Drop و Freeze ، لقد عرضت للتو Drop هنا لأنه من السهل شرح ذلك). عندما نصل إلى أداة إنهاء Drop بدون تعيين علامة Drop ، فإننا نتجاهل علامة النهاية Drop . هذا يسمح برمز مثل ما يلي:

{
    let mut x = None;
    // Drop flag for x: false
    let y = Some(Foo);
    // Drop flag for y: true
    x = y; // Dropping x is fine, because Drop flag for x is false
    // Drop flag for y: false, Drop flag for x: true
    x
    // Dropping y is fine, because Drop flag for y is false
}

هذا لا يحدث في وقت التقييم ، لذلك لا بأس بما يلي:

{
    let mut x = Some(Foo);
    if false {
        x = None;
    }
    x
}

نتحقق من أن جميع مسارات التنفيذ الممكنة لا تسبب Drop .

على الرغم من ذلك ، فإن التكاثر المستمر هو تشبيه جيد. إنها مشكلة أخرى في تدفق البيانات لا يمكن التعبير عن وظيفة النقل الخاصة بها باستخدام مجموعات gen / kill ، والتي لا تتعامل مع حالة النسخ بين المتغيرات. ومع ذلك ، يحتاج الانتشار المستمر إلى تخزين القيمة الفعلية لكل متغير ، ولكن التحقق الثابت يحتاج فقط إلى تخزين بت واحد يشير إلى ما إذا كان هذا المتغير يحتوي على عنصر Drop مخصص أم لا يجعله Freeze أقل تكلفة قليلاً من الانتشار المستمر.

لكي نكون واضحين ، فإن المثال الأول لـ @ oli-obk يجمع على المستقر اليوم ، ولديه منذ 1.38.0 ، والذي لم يتضمن # 64470.

علاوة على ذلك ، يُجمّع const X: Option<Foo> = None; منذ 1.0 ، وكل شيء آخر هو مجرد امتداد طبيعي من ذلك مع الميزات الجديدة التي اكتسبها const Eval.

حسنًا ، أعتقد أنه من المنطقي تبني الخيار القائم على القيمة البحتة حينئذٍ.

أعتقد أنه يمكننا تغطيته في الاجتماع وتقديم تقرير مرة أخرى =)

ملخص

أقترح أن نحقق الاستقرار في #![feature(const_if_match)] بالدلالات الحالية.

على وجه التحديد ، ستصبح تعبيرات if و match بالإضافة إلى عوامل منطق الدائرة القصيرة && و || قانونية في جميع سياقات const . سياق ثابت هو أي مما يلي:

  • مُهيئ لـ const أو static أو static mut أو تمييز التعداد.
  • جسم const fn .
  • قيمة عام ثابت (كل ليلة فقط).
  • طول نوع المصفوفة ( [u8; 3] ) أو تعبير مصفوفة مكرر ( [0u8; 3] ).

علاوة على ذلك ، لن يتم تخفيض مشغلي منطق الدائرة القصيرة بعد الآن إلى معادلاتها المعادلة ( & و | على التوالي) في const و static (انظر # 57175). نتيجة لذلك ، يمكن استخدام روابط let جنبًا إلى جنب مع منطق ماس كهربائى في تلك التهيئة.

مشكلة التتبع: # 49146
هدف الإصدار: 1.45 (2020-06-16)

تاريخ التنفيذ

قام 64470 بتنفيذ تحليل ثابت قائم على القيمة يدعم تدفق التحكم الشرطي ويعتمد على تدفق البيانات. هذا ، جنبًا إلى جنب مع # 63812 ، سمح لنا باستبدال كود التحقق الثابت القديم بآخر يعمل على الرسوم البيانية المعقدة للتحكم والتدفق. تم تشغيل مدقق const القديم بالتوازي مع المدقق المستند إلى تدفق البيانات لبعض الوقت للتأكد من موافقتهم على برامج ذات تدفق تحكم بسيط. # 66385 أزال المدقق القديم لصالح المدقق المستند إلى تدفق البيانات.

قام 66507 بتطبيق بوابة الميزة #![feature(const_if_match)] مع الدلالات المقترحة الآن لتحقيق الاستقرار.

تأهيل Const

خلفية

قامت [ميري] بدعم تقييم وظيفة الترجمة (CTFE) في rustc لعدة سنوات حتى الآن ، وتمكنت من تقييم العبارات الشرطية على الأقل لتلك الفترة الطويلة. أثناء CTFE ، يجب أن نتجنب عمليات معينة ، مثل استدعاء الضمانات المخصصة Drop أو أخذ إشارة إلى قيمة ذات قابلية تغيير داخلية . تُعرف هذه الخصائص غير المؤهلة بشكل جماعي باسم "المؤهلات" ، وتُعرف عملية تحديد ما إذا كانت قيمة ما لها مؤهل في نقطة معينة في البرنامج باسم "التأهيل الثابت".

ميري قادرة تمامًا على إصدار خطأ عندما تواجه عملية غير قانونية بقيمة محددة ، ويمكنها القيام بذلك دون أي نتائج إيجابية خاطئة. ومع ذلك ، يحدث CTFE بعد monomorphization ، مما يعني أنه لا يمكن معرفة ما إذا كانت الثوابت المحددة في سياق عام صالحة حتى يتم إنشاء مثيل لها ، وهو ما يمكن أن يحدث في صندوق آخر. للحصول على أخطاء ما قبل أحادية الشكل ، يجب أن ننفذ تحليلًا ثابتًا يقوم بتأهيل ثابت. في الحالة العامة ، لا يمكن تقرير مؤهل ثابت (انظر نظرية رايس ) ، لذلك فإن أي تحليل ثابت يمكن أن يقارب فقط عمليات التحقق التي تقوم بها ميري أثناء CTFE.

يجب أن يمنع تحليلنا الثابت الإشارة إلى نوع به قابلية تغيير داخلية (على سبيل المثال ، &Cell<i32> ) من الظهور في القيمة النهائية لـ const . إذا تم السماح بذلك ، يمكن تعديل const في وقت التشغيل.

const X: &std::cell::Cell<i32> = std::cell::Cell::new(0);

fn main() {
  X.get(); // 0
  X.set(42);
  X.get(); // 42
}

ومع ذلك ، نسمح للمستخدم بتحديد const الذي يحتوي نوعه على قابلية تغيير داخلية ( !Freeze ) طالما يمكننا إثبات أن القيمة النهائية لهذا const ليست كذلك. على سبيل المثال ، تم تجميع ما يلي منذ الإصدار الأول من الصدأ المستقر :

const _X: Option<&'static std::cell::Cell<i32>> = None;

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

const _: Option<Vec<i32>> = {
  let x = None;
  let mut y = x;
  y = Some(Vec::new()); // Causes the old value in `y` to be dropped.
  y
};

دلالات الليل الحالية

يوسع السلوك الحالي لـ #![feature(const_if_match)] الدلالات المستندة إلى القيمة للعمل على الرسوم البيانية المعقدة لتدفق التحكم باستخدام تدفق البيانات. بمعنى آخر ، نحاول إثبات أن المتغير لا يمتلك المؤهلات المطلوبة على طول جميع المسارات الممكنة من خلال البرنامج.

enum Int {
    Zero,
    One,
    Many(String), // Dropping this variant is not allowed in a `const fn`...
}

// ...but the following code is legal under this proposal...
const fn good(x: i32) {
    let i = match x {
        0 => Int::Zero,
        1 => Int::One,
        _ => return,
    };

    // ...because `i` is never `Int::Many` on any possible path through the program.
    std::mem::drop(i);
}

تشمل جميع المسارات الممكنة من خلال البرنامج تلك التي قد لا يتم الوصول إليها مطلقًا من الناحية العملية. مثال ، باستخدام نفس Int enum كما هو مذكور أعلاه:

const fn bad(b: bool) {
    let i = if b == true {
        Int::One
    } else if b == false {
        Int::Zero
    } else {
        // This branch is dead code. It can never be reached in practice.
        // However, const qualification treats it as a possible path because it
        // exists in the source.
        Int::Many(String::new())
    };

    // ILLEGAL: `i` was assigned the `Int::Many` variant on at least one code path.
    std::mem::drop(i);
}

يتعامل هذا التحليل مع استدعاءات الوظائف على أنها غير شفافة ، بافتراض أن قيمة الإرجاع الخاصة بها قد تحتوي على أي قيمة من نوعها. نعود أيضًا إلى التحليل القائم على النوع للمتغير بمجرد إنشاء مرجع قابل للتغيير إليه. لاحظ أن إنشاء مرجع قابل للتغيير في سياق ثابت ممنوع حاليًا على الصدأ المستقر.

#![feature(const_mut_refs)]

const fn none() -> Option<Cell<i32>> {
    None
}

// ILLEGAL: We must assume that `none` may return any value of type `Option<Cell<i32>>`.
const BAD: &Option<Cell<i32>> = none();

const fn also_bad() {
    let x = Option::<Box<i32>>::None;

    let _ = &mut x;

    // ILLEGAL: because a mutable reference to `x` was created, we can no
    // longer assume anything about its value.
    std::mem::drop(x)
}

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

البدائل

لقد وجدت صعوبة في التوصل إلى بدائل عملية ومتوافقة مع الإصدارات السابقة للنهج الحالي. يمكننا الرجوع إلى التحليل المستند إلى النوع لجميع المتغيرات بمجرد استخدام الشروط في سياق ثابت. ومع ذلك ، سيكون من الصعب أيضًا شرح ذلك للمستخدمين ، نظرًا لأن الإضافات التي تبدو غير مرتبطة قد تتسبب في عدم تجميع الكود ، مثل assert في المثال التالي من @ oli-obk.

const fn foo<T>(b: bool) {
    let x = Option::<T>::None;
    assert!(b);
    {x};
}

إن زيادة التعبير عن التحليل القائم على القيمة ليست مجانية. أظهر تشغيل الأداء الذي حقق تأهيلًا ثابتًا على جميع عناصر العناصر ، وليس فقط const منها ، انحدارًا بنسبة 5٪ عند إنشاءات الشيكات . هذا هو السيناريو الأسوأ ، لأنه يفترض أن جميع العناصر سيتم صنعها const في وقت ما في المستقبل. تمت مناقشة التحسينات الممكنة ، مثل تلك الموجودة في # 71330 ، مسبقًا في سلسلة الرسائل.

العمل المستقبلي

في الوقت الحالي ، يتم تشغيل التحقق الثابت قبل وضع الإسقاط ، مما يعني أن بعض أدوات إنهاء الإسقاط تظل في MIR التي يتعذر الوصول إليها في الممارسة العملية. هذا يمنع Option::unwrap من أن يصبح const fn (انظر # 66753). هذا ليس من الصعب حله ، ولكنه سيتطلب تقسيم ممر التحقق الثابت إلى مرحلتين (تفصيل قبل وبعد الإفلات).

بمجرد استقرار #![feature(const_if_match)] ، يمكن عمل قدر كبير من وظائف المكتبة const fn . يتضمن هذا العديد من العمليات على أنواع الأعداد الصحيحة الأولية ، والتي تم تعدادها في # 53718.

يتم حظر الحلقات الموجودة في سياق ثابت في نفس سؤال التأهيل الثابت مثل الشروط. يعمل النهج الحالي المستند إلى تدفق البيانات أيضًا مع CFGs الدورية بدون أي تعديلات ، لذلك إذا تم تثبيت #![feature(const_if_match)] ، فسيختفي الحاجز الرئيسي لـ # 52000.

شكر وتقدير

نتقدم بشكر خاص إلى @ oli-obk و eddyb ، اللذان كانا المراجعين الأساسيين لمعظم أعمال التنفيذ ، بالإضافة إلى بقية @ rust-lang / wg-const -uate لمساعدتي في فهم المشكلات ذات الصلة المتعلقة بـ const المؤهل. لن يكون أي من هذا ممكنًا بدون Miri ، الذي تم إنشاؤه بواسطة solson والذي يتم RalfJung و @ oli-obk.

هذا هو تقرير الاستقرار الذي يسبق FCP. لا يمكنني فتح FCP ، ومع ذلك.

@ ecstatic-morse شكراً جزيلاً لكم على كل ما تبذلونه من العمل الشاق بشأن هذه المسألة!

تقرير رائع!

الشيء الوحيد الذي أعتقد أنني أود أن أراه ، @ ecstatic-morse ، هو

  • روابط لبعض الاختبارات التمثيلية في الريبو ، حتى نتمكن من مراقبة السلوك
  • ما إذا كانت هناك آثار حول semver أو أي شيء آخر - أعتقد أن الإجابة هي إلى حد كبير لا ، أليس كذلك؟ بعبارة أخرى ، نحن نتخذ قرارًا بشأن التحليل المستخدم لتحديد ما إذا كان نص الثابت fn قانونيًا أم لا ، ولكن بالنظر إلى الثابت fn ، لا تحدد اختياراتنا هنا أشياء مثل "ما يمكن أن يفعله متصل التابع لـ const fn النتيجة "، أليس كذلك؟ أحاول معرفة ما يمكن أن يكون المثال لما أتحدث عنه - أفترض أنه سيكون أن المتصل لا يعرف بدقة متغيرات التعداد التي تم استخدامها ، فقط ذلك - مهما كانت القيمة تم إرجاعه - لم يكن لديه قابلية تغيير داخلية (والتي من المفترض أنه لا يمكنهم الاعتماد عليها عند المطابقة ، منذ ذلك الحين).

بعبارة أخرى ، نحن نتخذ قرارًا بشأن التحليل المستخدم لتحديد ما إذا كان نص الثابت fn قانونيًا أم لا ، ولكن بالنظر إلى الثابت fn ، لا تحدد اختياراتنا هنا أشياء مثل "ما يمكن أن يفعله متصل التابع لـ const fn النتيجة "، أليس كذلك؟ أحاول معرفة ما يمكن أن يكون المثال لما أتحدث عنه - أفترض أنه سيكون أن المتصل لا يعرف بدقة متغيرات التعداد التي تم استخدامها ، فقط ذلك - مهما كانت القيمة تم إرجاعه - لم يكن لديه قابلية تغيير داخلية (والتي من المفترض أنه لا يمكنهم الاعتماد عليها عند المطابقة ، منذ ذلك الحين).

نعم ، جسم الثابت fn معتم. هذا على عكس تعبير intializer للعنصر const . يمكنك ملاحظة ذلك من خلال حقيقة أن

const FOO: Option<Cell<i32>> = None;

يمكن استخدامها لإنشاء &'static Option<Cell<i32>>

const BAR: &'static Option<Cell<i32>> = &FOO;

بينما لا يمكن لـ const fn بنفس الجسم:

const fn foo() -> Option<Cell<i32>> { None }
const BAR: &'static Option<Cell<i32>> = &foo();

عرض الملعب

عندما نقدم التحكم في التدفق إلى الثوابت ، فهذا يعني ذلك

const FOO: Option<Cell<i32>> = if MEH { None } else { None };

سيعمل أيضًا ، بغض النظر عن قيمة MEH و

const FOO: Option<Cell<i32>> = if MEH { Some(Cell::new(42)) } else { None };

لن يعمل ، مرة أخرى ، غير ذي صلة بقيمة MEH .

لا يغير تدفق التحكم أي شيء بخصوص مواقع الاتصال التي تبلغ const fn ، فقط ما يتعلق بالكود المسموح به داخل هذا الثابت fn.

روابط لبعض الاختبارات التمثيلية في الريبو ، حتى نتمكن من مراقبة السلوك.

لقد أضفت فقرة في نهاية قسم "Current Nightly Semantics" ترتبط ببعض حالات الاختبار المثيرة للاهتمام. أشعر أننا بحاجة إلى مزيد من الاختبارات (بيان صحيح بغض النظر عن الظروف) قبل أن يستقر هذا ، ولكن يمكن معالجة ذلك بمجرد أن نقرر ما إذا كانت الدلالات الحالية مرغوبة.

ما إذا كانت هناك آثار حول semver أو أي شيء آخر.

بالإضافة إلى ما قاله @ oli-obk أعلاه ، أريد أن أشير إلى أن تغيير القيمة النهائية لـ const يعد تقنيًا تغييرًا جذريًا بالفعل:

// Upstream crate
const IDX: usize = 1; // Changing this to `3` will break downstream code!

// Downstream crate

extern crate upstream;

const X: i32 = [0, 1, 2][upstream::IDX]; // Only compiles if `upstream::IDX <= 2`

ومع ذلك ، نظرًا لأنه لا يمكننا إجراء تأهيل ثابت بدقة كاملة ، فإن تغيير ثابت لاستخدام if أو match يمكن أن يكسر الكود النهائي ، حتى لو لم تتغير القيمة النهائية. فمثلا:

// Changing from `cfg` attributes...

#[cfg(not(FALSE))]
const X: Option<Vec<i32>> = None;
#[cfg(FALSE)]
const X: Option<Vec<i32>> = Some(Vec::new());

// ...to the `cfg` macro...

const X: Option<Vec<i32>> = if !cfg!(FALSE) { None } else { Some(Vec::new() };

// ...could break downstream crates, even though `X` is still `None`!

// Downstream

 // Only legal if static analysis can prove the qualifications in `X`
const _: () =  std::mem::drop(upstream::X); 

لا ينطبق هذا على التغييرات داخل جسم const fn ، لأننا نستخدم دائمًا التأهيل المستند إلى النوع لقيمة الإرجاع ، حتى داخل الصندوق نفسه.

من وجهة نظري ، "الخطيئة الأصلية" هنا لم تكن تتراجع إلى التأهيل القائم على النوع لـ const و static s المحدد في الصناديق الخارجية. ومع ذلك ، أعتقد أن هذا هو الحال منذ الإصدار 1.0 ، وأعتقد أن الكثير من الكود يعتمد عليه. بمجرد أن تسمح لمُهيئ ثابت لا يمكن أن يكون التحليل الساكن دقيقًا تمامًا له ، يصبح من الممكن تعديل هؤلاء المُهيئين بطريقة تجعلهم ينتجون نفس القيمة دون أن يتمكن التحليل الثابت من إثبات ذلك.

تعديل:

لا يوجد شيء فريد حول if و match في هذا الصدد. على سبيل المثال ، يعد حاليًا تغييرًا مفاجئًا لإعادة بناء مُهيئ const إلى مُهيئ const fn إذا كان صندوق المصب يعتمد على مؤهل قائم على القيمة.

// Upstream
const fn none<T>() -> Option<T> { None }

const VALUE_BASED: Option<Vec<i32>> = None;
const TYPE_BASED: Option<Vec<i32>> = none();

// Downstream

const OK: () = { std::mem::drop(upstream::VALUE_BASED); };
const ERROR: () = { std::mem::drop(upstream::TYPE_BASED); };

@ ecstatic-morse شكرًا لك على كتابة تقرير التثبيت! دعونا نقيس الإجماع بشكل غير متزامن:

rfcbot دمج

إذا أراد أي شخص مناقشة هذا بشكل متزامن في اجتماع ، يرجى إعادة ترشيحه.

اقترح عضو الفريق joshtriplett دمج هذا. الخطوة التالية هي المراجعة بواسطة باقي أعضاء الفريق المميزين:

  • [x]cramertj
  • [x] @ joshtriplett
  • [x]nikomatsakis
  • [x]pnkfelix
  • [] @ scottmcm
  • [] @ بدون قوارب

لا مخاوف مدرجة حاليا.

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

راجع هذا المستند للحصول على معلومات حول الأوامر التي يمكن أن يقدمها لي أعضاء الفريق.

: bell: هذا يدخل الآن فترة التعليق النهائية ، وفقًا للمراجعة أعلاه . :جرس:

هل يسمح هذا أيضًا باستخدام ? في const fn ؟

استخدام ? يعني استخدام السمة Try . استخدام السمات في const fn غير مستقر ، راجع https://github.com/rust-lang/rust/issues/67794.

TimDiekmann في الوقت الحالي ، سيكون عليك كتابة وحدات ماكرو proc التي تخفض قيمة؟ يدويا. نفس الشيء ينطبق على loop و for ، على الأقل حتى حد معين (أسلوب العودية البدائي) لكن تقييم const يحتوي على مثل هذه الحدود على أي حال. هذه الميزة رائعة للغاية ، فهي تتيح الكثير من الأشياء التي لم تكن ممكنة من قبل. يمكنك حتى بناء wasm vm صغير في const fn إذا كنت تريد.

اكتملت الآن فترة التعليق النهائية ، مع الاستعداد للدمج ، وفقًا للمراجعة أعلاه .

بصفتي الممثل الآلي لعملية الحوكمة ، أود أن أشكر المؤلف على عمله وكل من ساهم.

سيتم دمج RFC قريبًا.

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