Rust: مشكلة التتبع للأدوية الثابتة (RFC 2000)

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

مشكلة في تتبع rust-lang / rfcs # 2000

التحديثات:

إذا كنت تريد مساعدة، نلقي نظرة على القضايا الأدوية CONST مفتوحة ، وتتردد فيvarkor بينغ،eddyb،yodaldevoid، @ اولى-obk أوlcnr للمساعدة في البدء!


منع الاستقرار:

  • [ ] تصميم:

    • [] حل ترتيب المعلمات الثابتة والنوع ، مع المعلمات الافتراضية

    • [] حدد أفضل موازنة لتجربة المستخدم / تكلفة التنفيذ لتوحيد تعبيرات الإنشاء المجردة.

    • [] كيف نحدد التشكيل الجيد لتعبيرات الكون.

  • [x] التنفيذ
  • [ ] توثيق

    • [] دليل rustc


قضايا التنفيذ المتبقية:

  • [] حل العديد من التعليقات FIXME(const_generics) .
  • [] حل المشكلات المتعلقة بالتطبيع المتعارف عليه / التطبيع البطيء.
  • [] التحقيق في التعامل مع معلمات const في الأنماط.
  • [] أضف المزيد من الاختبارات.
  • [] تنفيذ الإعدادات الافتراضية لمعلمات const ( FIXME(const_generics:defaults) ).
  • [] إصلاح مشكلات A-const-Genics الأخرى .
  • [] استخدامات التدقيق has_infer_types .
  • [x] نمنع استخدام التعبيرات المعقدة للوسيطات الثابتة التي تتضمن معلمات (حاليًا) ، على سبيل المثال {X * 2} .
  • [] تدقيق التشخيص (مثل https://github.com/rust-lang/rust/pull/76401#discussion_r484819320).
A-const-fn A-const-generics A-typesystem B-RFC-approved C-tracking-issue F-const_generics T-compiler T-lang requires-nightly

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

فيما يلي ملخص للتقدم المحرز حتى الآن في الأدوية العامة.


قبل أن يبدأ العمل على الأدوية العامة الثابتة بشكل صحيح ، كان هناك بعض إعادة الهيكلة التي يجب القيام بها. تولى jplatte المهمة مع https://github.com/rust-lang/rust/pull/45930. بعد ذلك ، بدأ jplatte العمل على التطبيق الرئيسي للأدوية الثابتة ، لكنه اكتشف أنه لم يكن لديه الوقت الكافي للمتابعة.

التقطت أنا و yodaldevoid المكان الذي توقفت فيه https://github.com/rust-lang/rust/pull/48149 ، https://github.com/rust-lang/rust/pull / 48452 ، https://github.com/rust-lang/rust/pull/48523 ، https://github.com/rust-lang/rust/pull/51880.

مع القيام بذلك ، يمكن أن يبدأ تطبيق الأدوية العامة بجدية. منذ ذلك الحين ، عملت أنا و https://github.com/rust-lang/rust/pull/58191 ، https://github.com/rust-lang/rust / pull / 58503 ، https://github.com/rust-lang/rust/pull/58581 ، https://github.com/rust-lang/rust/pull/58583 ، https://github.com/rust -lang / rust / pull / 59170 ، https://github.com/rust-lang/rust/pull/59355 ، https://github.com/rust-lang/rust/pull/59415 ، https: // github .com / rust-lang / rust / pull / 60058 ، https://github.com/rust-lang/rust/pull/60280 ، https://github.com/rust-lang/rust/pull/60284 and most مؤخرًا https://github.com/rust-lang/rust/pull/59008. (تم فصل هذه في الغالب عن


ما هو الوضع الآن؟ تعمل بعض الاختبارات العامة لـ const ومع ذلك ، لا تزال هناك اختبارات لا تعمل ، وهناك عدد من FIXME s في جميع أنحاء الكود الذي لا يزال يتعين علينا معالجته. نحن نقترب الآن ، رغم ذلك ، ونحن في مرحلة حيث توجد بعض الفاكهة المتدلية إذا كنت تريد المساعدة.

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

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

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

ال 202 كومينتر

أضاف 44275 قيمة المسند ConstEvaluatable ، و WF([T; expr]) يتطلب الآن ConstEvaluatable(expr) ، حيث يتم تقييم expr بتباطؤ (حتى لو كان مجرد عدد صحيح حرفية). يتطلب تحقيق هذا الإسناد أن يتم تقييم التعبير بنجاح ، بينما يتجاهل التسوية الخطأ ويترك ببساطة التعبير Unevaluated الذي وجده دون تغيير ، وهو ما يحدث تقريبًا مع توقعات النوع المقترنة. أتوقع أن يتوسع نفس النظام ليشمل الأدوية العامة.

عبرEpicatSupercell عن اهتمامه بالعمل على هذا ،

وهذا يعني أننا بحاجة إلى التطبيع البطيء لـ

نقاط طريق التنفيذ (لمزيد من التوجيه المباشر ، ابحث عن @eddyb على Gitter أو eddyb على IRC):

  • إعلان / بناء الجملة:
  • إعلان / دلالات

    • هياكل البيانات: ty::Generics - أضف معلمات const إلى جانب معلمات النوع

    • التحويل من HIR: generics_of - إنشاء ty::ConstParameterDef من hir::ConstParam

  • استخدام / تحليل الاسم

    • هياكل البيانات: Def - أضف متغيرًا لمعلمات const

    • تمرير تحليل الاسم: with_type_parameter_rib - يدعم كلا النوعين و const generics

  • استخدام / دلالات

    • ConstVal - أضف متغير Param أقرب إلى ty::TyParam

    • التحويل من HIR: TyArray بطول يساوي ExprPath والذي تم حله إلى Def::ConstParam يجب أن يستخدم ConstVal::Param بدلاً من ConstVal::Unevaluated - في مماثل أزياء لكيفية تحول Def::TyParam إلى ty::TyParam

    • subst::Kind - دعم &ty::Const وتحقق من as_const أيضًا في الأماكن التي يتم فيها تحديد as_type و as_region

  • الإستنباط

    • ConstVal - أضف متغير InferVar أقرب إلى ty::ReVar / ty::TyInfer(TyVar(_))

    • InferCtxt - const نظرائهم إلى int_unification_table و UnifyKey

    • ty::relate::{Relate,TypeRelation} - الدعم المتعلق بـ ty::Const ، وتعامل مع ConstVal::InferVar بطريقة مشابهة لكيفية عمل super_combine_tys للأنواع

لاحظ أن كل هذا يجب أن يسمح impl<T, const N: usize> Trait for [T; N] {...} ، لكن لا يتم تمرير تعبير ثابت إلى نوع / وظيفة ، على سبيل المثال ArrayVec<T, 3> .

أود أن أحصل على طعنة في هذا :)

jplatteeddyb هل من أخبار عن هذا؟

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

jplatte سيكون

لا يوجد علاقات عامة بعد. يمكن العثور على كل عملي هنا .

عمل جيد حتى الآن jplatte 🍻

يوجد الآن علاقات عامة للأعمال الأساسية ( Generics إعادة بناء ديون): # 45930

أعتقد أن هذا تم تضمينه بالفعل ولكن سيكون من الجيد التعامل مع أسلوب طي النمط C ++ للتعامل مع مصفوفات الأبعاد بأطوال متفاوتة على غرار الجبر الخطي ، IE a 4x4 [[f64؛ 4]؛ 4] أو مصفوفة أبعاد 4x3x5x6 [[[[] f64؛ 6]؛ 5]؛ 3]؛ 4] وأن تكون قادرًا على الالتفاف بشكل صحيح وإنشاء طرق متخصصة لكل من عمليات التنفيذ المناسبة للسمات العددية المتجهات ذات الأبعاد المناسبة ، إلخ. راجع https://gist.github.com/huhlig / 8b21850b54a75254be4b093551f8c2cb لمثال أولي.

لا أتذكر أي شخص اقترح تعبيرات مطوية لـ Rust من قبل ، ناهيك عن ذلك كجزء من RFC هذا. ولكن نظرًا لأن هذا هو Rust ، فهل هناك أي سبب لعدم تمكننا من تنفيذ تعبيرات الطي كماكرو عادي ، بدلاً من بناء جملة مخصص جديد؟

ما هي الخطوات التالية الآن بعد دمج # 45930؟ تضمين التغريدة

kjaleshire والخطوة التالية هي إجراء تحليل لأدوية const تعليق eddyb إلى أعلى). لقد بدأت العمل بالفعل على هذا قبل أن يتضح أن إعادة البناء في إعادة البناء سيكون ضروريًا. يمكن العثور على عملي الحالي حول ذلك هنا ؛ لم يتم إعادة تأسيسه بعد منذ أن تم دمج العلاقات العامة الخاصة بإعادة الهيكلة.

jplatte أعتقد أنك قصدت ذكر kjetilkjeka.

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

jplatte لا تريد أن تكون غير صبور ، ولكن هل كان هناك أي عمل على هذا؟ هل تحتاج مساعدة؟ هل يجب على أحد المساعدة؟

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

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

jplatte ~ None في الأول وليس في الثانية ~~ (ج جpnkfelixnikomatsakis)

تحرير : لا شيء تفعله في كلتا الحالتين.

eddyb لأول مقتطف مرتبط ، هل أنت متأكد من أنه يجب إرجاع None ؟ قد لا أفهم ما يجري هنا ، لكن يبدو لي أنه لا ينبغي فعل أي شيء. إذا تم إرجاع None سيتم تخطي المعلمات الأخرى التي قد تكون غير آمنة.

yodaldevoid معذرة ، أنت على حق ، لم أدرك أن هذا كان على Generics .

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

yodaldevoid عظيم أن نسمع. لا أعرف شيئًا عن Gitter ، لكنك ستحصل بالتأكيد على الكثير من الإرشادات حول #rustc و / أو # rust-internals على IRC!

yodaldevoid : هل ستكون فعلته حتى الآن هنا .) ربما يمكننا الدردشة على IRC (#rustc or # rust-internals) حول هذا الموضوع؟

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

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

@ qwerty19106
يتم إحراز تقدم في هذا ، وإن كان ببطء. varkor وأنا نعمل على هذا الأمر وإيقافه كما كان لدينا الوقت. لقد أحرزت بعض التقدم هذا الأسبوع ونرى الضوء في نهاية النفق للاستخدام الأساسي.

إلى جانب تطبيق الأدوية العامة ، قمنا (varkor) ببعض التنظيف لجعل كل هذا ممكنًا (انظر # 48149 و # 48523). أعتقد أن الخطة الحالية هي انتظار تنفيذ طلبي السحب هذين قبل استخدام الأدوية العامة ، لكن يمكن لـ varkor التحدث أكثر عن ذلك.

أنا أتفهم حقًا حاجتك للأدوية العامة للعمل المضمن. لقد بدأت في هذا لأنني أيضًا أريد حقًا أنواعًا ثابتة حتى أتمكن من تنظيف مساحات كبيرة من التعليمات البرمجية المضمنة وجعلها آمنة.

TL ؛ DR: التقدم مستمر ، لكن هذا معقد. أشعر بك في المقدمة.

بالنسبة إلى مربع الاختيار "التوثيق" ، سيكون من الرائع الحصول على شيء ما في دليل rustc .

شكرا yodaldevoid على ردك. سوف أتطلع إلى نهاية عملك.

تحديث لأولئك الفضوليين (منذ أن كنت فضوليًا أيضًا). رد: الممثلين الرئيسيين المذكورين أعلاه : تم دمج # 48523 و # 48149 يحرز تقدمًا باطراد.

@ مارك- im الأشياء الجيدة! عمل رائع بواسطةvarkor. ما هو موعد إيتا تقريبًا ، هل تعلم؟ :-)

في صحتك ، @ flip111.

يبدو أن ثاني أكبر عملية إعادة بناء ديون PR # 48149 قد تم دمجها :)

/ سم مكعب لي

التالي varkor PR # 51880

أردت فقط تقديم تحديث سريع ، حيث أعلم أن بعض الأشخاص يسألون عن التقدم في الأدوية العامة الثابتة.

لإعطاء بعض السياق ، في مارس / آذار ، كان لدي أنا و yodaldevoid تنفيذ أولي كان على

علاوة على ذلك ، فقد تقرر أن كود المعلمات العامة بحاجة إلى التنظيف بشكل عام قبل معالجة العوامل الثابتة ، لتحسين إمكانية القراءة ، ولكن أيضًا لارتكاب أخطاء حيث نسينا التعامل مع الأدوية العامة الثابتة في حالة معينة أصعب صنع. تم ذلك في https://github.com/rust-lang/rust/pull/48523 ، https://github.com/rust-lang/rust/pull/48149 وسيتم إكماله في https: // github. كوم / رست لانج / صدأ / سحب / 51880. كانت هذه أكثر انخراطًا قليلاً مما كنت أتوقعه في البداية ، وقد استغرقت وقتًا أطول قليلاً للمضي قدمًا مما كان متوقعًا.

في غضون ذلك ، نعمل أنا و https://github.com/rust-lang-nursery/chalk تقدمًا جيدًا ، والذي ينبغي أن يعالج بعض الصعوبات الموضحة أصلاً على eddyb .)


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

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

ما أعنيه هو أن طريقة بسيطة نسبيًا للتحقق من تساوي التعبيرات التركيبية المجردة هي كالتالي:

  • يتعامل تلقائيًا مع المساواة النحوية (على سبيل المثال ، يجب أن يعمل N+1 == N+1 خارج الصندوق)
  • السماح للمستخدم ، في وقت التعريف ، بإضافة معادلات مثل N+M == M+N (ربما في عبارة where ؟). يمكن استخدام هذه المعادلات عن طريق فحص المساواة (باستخدام شكل من أشكال إغلاق التطابق). تعريف لا يكتب التحقق باستخدام هذه المعادلات المقدمة مرفوض.
  • عند نقطة توسع أحادية الشكل ، يمكن التحقق من جميع المعادلات عن طريق حساب exprs في الواقع ، والتي لم تعد مجردة بعد الآن. يوجد هنا خيار تصميم: إذا كانت المعادلة تقلص إلى false ، فقد يكون هناك خطأ في التجميع ("المعادلات هي بديهيات") أو لا يمكن إنشاء مثيل لها ("المعادلات هي قيود")
  • عند نقطة توسع ذات معلمات ، يتم ترحيل هذه المعادلات: إذا كان لديك دالة f حدّدتها N حيث N+0==N ، يجب ألا تضيع هذه المعادلة في المتصل g لأنه سيتعين فحصه في كل مكان أحادي الشكل حيث يتم استدعاء g .

محاسن هذه الطريقة هي أنه لا توجد حاجة لمبرهن نظري ، أو محلل SMT ، أو إعادة كتابة حسابية في لغة Rustc نفسها. "فقط" تحقق من المساواة النحوية للأنواع والأسماء المستعارة للوحدات النمطية ومجموعة المعادلات التي يوفرها المستخدم.
العيوب هي أنه يدوي أكثر للمستخدم حيث يجب إضافة مساواة واضحة على ما يبدو مثل M+N=N+M بشكل صريح.

مثال:

/// this works directly because of syntactic checks
fn add_end<T:Copy, const N: usize>(a: &[T;N], b: T) -> [T;N+1] {
  let x : [T;N+1] = [b;N+1];
  x[0..N] = a;
  x
}

/// this should work already
fn append<T:Copy, const M:usize, const N:usize>(a: &[T;M], b: &[T;N])
  -> [T;{M+N}]
{ … }

/// Here the equation M+M==N must be carried over or checked whenever this function is used
fn sum_pairwise_append<const M: usize, const N: usize>(a: &[i32, M],b: &[i32;N])-> [T;N]
  where M+M == N {
  let mut res : [i32; N] = append(a,a);
  for i in 0 .. N { res[i] += b[i] };
  res
} 


fn main() {
  let a: [i32; 2] = [1;2];
  let b: [i32; 4] = [2;4];
  let _ = sum_pairwise_append(a, b);  // need to check 2+2=4 
}

المعادلات كبديهيات

هذا يعني أن e1 == e2 يجب أن يكون دائمًا صحيحًا ، لذا فهو ليس قيدًا where ولكنه يشبه إلى حد كبير assert_eq!(e1,e2) الذي يمكن استخدامه بواسطة مدقق النوع. هنا يقدم المنفذ وعدًا بأن هذا صحيح دائمًا ، ويعرض مستخدميه لأخطاء التجميع إذا قدموا معلمة تدحض المعادلة.

المعادلات كقيود

هنا شرط where e1 == e2 هو قيد يجب استيفاؤه من أجل الاستخدام الناجح لهذه السمة / الوظيفة ذات المعلمات. هذا يعني أن e1 == e2 ليس مضطرًا إلى الاحتفاظ به دائمًا ، وهو ما قد يكون مثيرًا للاهتمام بالنسبة للمعادلات التي تنطبق فقط على النطاق ، مثل (x*y) / z == (y*x) / z الذي قد يفشل في إنشاء مثيل لـ z==0 .

@ c-cube لدينا بالفعل نظام لـ "عبارات ضمنية where " ، على الأقل للوظائف ، مشتقة من قواعد " WF (شكل جيد)" ، أي إذا حددت fn foo<'a, 'b>(x: &'a &'b i32) {} ثم يتطلب من المتصلين إرضاء 'b: 'a (كنتيجة للحاجة إلى WF(&'a &'b i32) -> &'b i32: 'a -> 'b: 'a ).

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

يبدو أن معظم كل شيء آخر تصفه قريبًا مما هو مخطط له (بما في ذلك شكل من أشكال "المساواة النحوية") ، لكننا لا نريد عمليات تحقق "monomorphization-time" ، يمكننا بدلاً من ذلك الحصول على طرق (إما ضمنيًا أو من خلال where عبارات أو بخلاف ذلك إذا كان بإمكاننا تقييمها ولم تصادفها.

يبدو أن معظم كل شيء آخر تصفه قريبًا مما هو مخطط له

eddyb هل تعرف أي

@ flip111 على الأرجح بعض طلبات التعليقات. ربما يعرف withoutboats أفضل.

# 51880 انتهى: تادا :: تادا:

withoutboats @ oli-obk ما رأيك في منع التوحيد الصحيح لتعبيرات مثل N + 1 (من على سبيل المثال [T; N + 1] ) للحصول على شكل أساسي من التقييم الرمزي في miri ؟

أعتقد أنه كان لدينا بالفعل آلية لتشفيرها ، عندما يضيف ConstValue::{Infer,Param} ، يمكننا استخدام ذلك لتتبع قيم "(رمزية) (سطحية) صالحة ولكن غير معروفة" ، ثم تضمين القيمة أيضًا (بشكل أساسي) أعداد صحيحة) وعمليات مكالمات فوق ذلك.

أي قرارات بخلاف assert التحكم في التدفق ستتطلب قيمًا معروفة ، ولكن ربما يمكن إعادة تعيين assert نفسه على أنه AssertThen(condition, assert message, success value) .
(يمكن أن يكون كل من condition و success value رمزًا!)

القدرة على تصدير القيم الرمزية إلى ty::Const تعني أنه يمكننا تنفيذ بعض التوحيد خارج ميري ، مع معاملة (معظم؟) العمليات على أنها مبهمة.

يجب أن نكون حريصين على عدم افتراض أي شيء من متغيرات الاستدلال ، ولكن على سبيل المثال N + 1 أعتقد أنه يمكننا دعم توحيد اثنين Add(Param(N), Bits(1)) معًا.

varkor حالة اختبار أعتقد أنها يجب أن تعمل مع التطبيع

/*const*/ fn append<const N: usize, T>(xs: [T; N - 1], x: T) -> [T; N] {
    let new = MaybeUninit::<[T; N]>::uninitialized();
    unsafe {
        let p = new.as_mut_ptr() as *mut T;
        (p as *mut _).write(xs);
        p.add(N - 1).write(x);
    }
    new.into_inner()
}

هذا من شأنه أن يعمل فقط للأسباب التالية:

  • يظهر N - 1 على مستوى النوع مرة واحدة بالضبط

    • كل شيء يمكن أن يشير إلى هذا التعبير ، بشكل مبهم

    • (الحل المحتمل : type ArrayWithoutLast<T, const N: usize> = [T; N - 1]; )

  • انها في موقف حجة داخل التوقيع

    • (لا أتذكر ما إذا كان موضع الإرجاع سيعمل أيضًا.nikomatsakis؟)

    • يحصل المتصلون على إثبات أنه WF ، من خلال تقديم قيم محددة لـ N

    • يتطلب "إنشاء فقاعات" متطلبات WF التوحيد / ArrayWithoutLast

    • قد تحتاج الاستخدامات الأخرى إلى "التضمين في عبارة where " مثل [T; N - 1]: Sized



      • يمكن حتى إساءة استخدام where [T; N - 1]: (هل يتم تجاهل ذلك اليوم؟ ouch!)


      • مرة أخرى تجاوز التوحيد مع where ArrayWithoutLast<T, N>: ...



لذا بشكل عام ، يمكننا على الأرجح الاعتماد على قواعد WF لفرض "التحقق من صحة" تعبيرات const على المستخدمين ، لكننا ما زلنا نريد التوحيد لأشياء أخرى (بما في ذلك عدم الحاجة إلى اختراق مثل ArrayWithoutLast ).

53645

سؤال صغير ينشأ من مناقشة وحدات القياس. ماذا يجب أن نفعل إذا كان النوع العام على الثابت لا يعتمد عليه بشكل مباشر؟ على سبيل المثال:

struct Foo<T, const N: usize> {
    a: T,
    // Will such array be "the way" to handle this problem?
    // Or do we want some kind of `std:marker::PhantomConstData`? (which can be a simple
    // type alias to the same array)
    // Or maybe make `PhantomData` to accept constants?
    _phantom: [(), N],
}

_phantom: [() ، N] ،

أفترض أنك كنت تقصد [(); N] ، لكن هذا لن يعمل إلا مقابل usize .

أعتقد أنه سيكون من المنطقي أن يكون لديك marker::PhantomConst يسمح بأي نوع const .

حسنًا ... إعادة قراءة طلب التعليقات مع أخذ التعليقات الأخيرة في الاعتبار ، أتساءل: هل يُسمح بشيء كهذا؟

struct Foo<T, const V: T> {
    _phantom: PhantomConst<T, V>,
}

لا أستطيع أن أرى أنه تم حظره في أي مكان ، لكني كنت أعتقد أنه يستحق مثالاً على الأقل.

Ekleog : على حد

كيف يتم التقدم في هذا؟ هل نعرف وقتًا تقريبيًا يجب أن يحدث هذا كل ليلة؟

Zauberklavier بمجرد الانتهاء من طلب السحب هذا . اقتبس منه:

هناك طريق طويل لنقطعه

newpavlov افترضت أنه سيتم السماح بالمعلمات الثابتة دون استخدامها في الحقول.
يجب استخدام معلمات نوع السبب بسبب التباين ، لكن الثوابت لا تحتوي على هذه المشكلة.

eddyb هذا ما أذكره من مناقشة RFC أيضًا.

varkor هذا يعني أن PhantomConst اقترحه cuviper لا يمكن أن يوجد في الحالة الحالية لـ RFC ... أليس كذلك؟ على الرغم من أن التعليقات الأخيرة تشير إلى أنه لا توجد حاجة لـ PhantomConst أي حال.

هل تؤثر معاملات const على تباين معلمات النوع التي تتضمنها؟

أعتقد حاليًا أنه لا يمكن أن تحتوي الأدوية العامة الثابتة على معلمات نوع في نوعها.

لست واضحًا بشأن ما يمكن أن تفعله النسخة الأولى العاملة من هذا.

على سبيل المثال ، ما إذا كانت الشفرة في هذا التعليق ستجمع:
https://github.com/rust-lang/rfcs/pull/2581#discussion_r230043717

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

@ rodrimati1992 يمكنك على الأرجح عمل (): IsTrue<{N < 128}> بدون نوع منفصل.
أعتقد أنك تريد إعادة استخدام القيد وهل يعمل بالفعل؟ (لأن نسخ التعبير N < 128 لن ينجح في البداية)
أعتقد أنه يمكنك استخدام trait Lt128<const N: usize> = IsTrue<{N < 128}>; .
هناك أيضًا خيار كتابة where [(); 128 - N], ، على ما أعتقد (لكنني لست متأكدًا من أننا نضمن أن ذلك سيؤدي إلى الذعر).

@ rodrimati1992 يمكنك على الأرجح عمل (): IsTrue<{N < 128}> بدون نوع منفصل.
أعتقد أنك تريد إعادة استخدام القيد وهل يعمل بالفعل؟ (لأن نسخ التعبير N < 128 لن ينجح في البداية)
أعتقد أنه يمكنك استخدام trait Lt128<const N: usize> = IsTrue<{N < 128}>; .
هناك أيضًا خيار كتابة where [(); 128 - N], ، على ما أعتقد (لكنني لست متأكدًا من أننا نضمن أن ذلك سيؤدي إلى الذعر).

لذا ، باستخدام الأسماء المستعارة للسمات التي يمكنني إعادة كتابتها هل هذا ؟:

trait AssertLessThan128<const N:usize>=
    Assert<{N<=128}, (
        Str<"uint cannot be constructed with a size larger than 128,the passed size is:",
        Usize<N>>
    ) >;

الفكرة مع Assertتستخدم سمة خطأ نوع لطباعة رسالة خطأ مضمنة في نوع ، والتي في حالة AssertLessThan128 هي:

(Str<"uint cannot be constructed with a size larger than 128,the passed size is:",Usize<N>>)

والذي أتوقع أن يكون أكثر فائدة من where [(); 128 - N], ، لأنه يخبرك في رسالة الخطأ عن سبب حدوث خطأ وقت الترجمة.

يمكنك أيضًا القيام بـ if !(N < 128) { panic!("...") } بشكل ثابت ، على ما أعتقد؟

اعتقدت أن بنية std :: fmt لن تكون موجودة حتى const trait قيود

مع هذا الشيء يمكن أن يكون لديك رسائل خطأ بقيم متعددة فيه (مضمنة في الأنواع).

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

@ rodrimati1992 انظر https://github.com/rust-lang/rfcs/blob/master/text/2345-const-panic.md ، ستكون هناك حالة خاصة للحصول على panic!() قبل أن تحصل عليها أن يكون ممكنًا عبر ميزات أخرى (على الأرجح لن يسمح بالتنسيق المخصص للقيم في البداية).

@ rodrimati1992 آه ، أرى أن هذه خدعة ذكية حقًا!

ما هي حالة هذا؟

الخطوة التالية لا تزال https://github.com/rust-lang/rust/pull/53645 AFAIK.

هذا صحيح. لإعطاء تحديث سريع لأولئك الذين لا يتبعون PR # 53645 ، تم تجميع ملفات const Genics والعمل في حالة استخدام واحدة بسيطة على الأقل. ما تبقى هو الانتهاء من codegen لحالات استخدام أخرى ، بما في ذلك العوامل الثابتة في arrys ، وبعض تنظيف إخراج الأخطاء. بعد ذلك ، يجب أن تكون العلاقات العامة جاهزة للدمج ويمكن للأشخاص البدء في اللعب بها.

قد يكون خارج الموضوع ، لكن هل سيسمح ذلك لمتغير أو تفرع من القطع والطرق ذات الصلة بأن يكون Item مصفوفة ذات حجم ثابت للترجمة بدلاً من شريحة؟ سيسمح هذا لحلقة for بالتدمير / الارتباط بنمط لا يمكن دحضه يقوم بتعيين العناصر في القطعة إلى متغيرات ، مثل for (first, second) in arr.chunks(2) الذي فشل حاليًا ، وأنا أخمن (بدون أي مبرر باعتراف الجميع) أنه سيسمح بمزيد من التحسين في حالات استخدام معينة.

jeffvandyke ربما تفكر في ChunksExact على وجه التحديد. سيكون مثل هذا التغيير كسرًا لواجهة برمجة التطبيقات ، لذا لا يمكن القيام به. يمكننا إضافة واجهات برمجة تطبيقات جديدة تقدم مراجع مصفوفة في المستقبل ، لكن لا يمكننا كسر الموجود منها.

jeffvandyke ربما تفكر في ChunksExact على وجه التحديد. سيكون مثل هذا التغيير كسرًا لواجهة برمجة التطبيقات ، لذا لا يمكن القيام به. يمكننا إضافة واجهات برمجة تطبيقات جديدة تقدم مراجع مصفوفة في المستقبل ، لكن لا يمكننا كسر الموجود منها.

أنا فقط في انتظار تنفيذ هذا واستقراره قبل اقتراح العلاقات العامة التي تضيف واجهة برمجة التطبيقات هذه بالإضافة إلى ChunksExact ومتغيراتها :)

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

ليتم تنفيذها واستقرارها

أنا أقترح لا تنتظر لتحقيق الاستقرار على هذا النحو لAPI سيكون واحدا الاستخدام الجيد لمساعدة ممارسة هذه الميزة لتحقيق الاستقرار.

أظن أن هذا لا يعمل حتى الآن مع كتل impl ؟ حاولت

#![feature(const_generics)]

struct The<const Val: u64>();

impl<const Val: u64> The<Val> {
    fn the() {
        println!("{}", Val);
    }
}

ولكن ، كما تم تحذيره بالفعل ، تعطل المترجم مع

thread 'rustc' panicked at 'slice index starts at 1 but ends at 0', src/libcore/slice/mod.rs:2419:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
   1: std::sys_common::backtrace::_print
   2: std::panicking::default_hook::{{closure}}
   3: std::panicking::default_hook
   4: rustc::util::common::panic_hook
   5: std::panicking::rust_panic_with_hook
   6: std::panicking::continue_panic_fmt
   7: rust_begin_unwind
   8: core::panicking::panic_fmt
   9: core::slice::slice_index_order_fail
  10: rustc_resolve::Resolver::resolve_ident_in_lexical_scope
  11: rustc_resolve::Resolver::resolve_path
  12: rustc_resolve::Resolver::resolve_path_without_parent_scope
  13: rustc_resolve::Resolver::smart_resolve_path_fragment
  14: rustc_resolve::Resolver::smart_resolve_path
  15: <rustc_resolve::Resolver<'a> as syntax::visit::Visitor<'tcx>>::visit_ty
  16: syntax::visit::walk_generic_args
  17: syntax::visit::walk_ty
  18: rustc_resolve::Resolver::with_generic_param_rib
  19: rustc_resolve::Resolver::resolve_item
  20: rustc_resolve::Resolver::resolve_crate
  21: rustc::util::common::time
  22: rustc_interface::passes::configure_and_expand_inner
  23: rustc_interface::passes::configure_and_expand::{{closure}}
  24: <rustc_data_structures::box_region::PinnedGenerator<I, A, R>>::new
  25: rustc_interface::passes::configure_and_expand
  26: <rustc_interface::queries::Query<T>>::compute
  27: <rustc_interface::queries::Query<T>>::compute
  28: <rustc_interface::queries::Query<T>>::compute
  29: rustc_interface::queries::<impl rustc_interface::interface::Compiler>::prepare_outputs
  30: rustc_interface::interface::run_compiler_in_existing_thread_pool
  31: <std::thread::local::LocalKey<T>>::with
  32: <scoped_tls::ScopedKey<T>>::set
  33: syntax::with_globals

الخطأ متعلق بـ const في impl<const Val: u64> حيث أن إزالة هذا الجزء تسبب أخطاء أخرى ولكن لا يحدث عطل.

لكن الدعائم ل Rust حتى حتى النظر في هذه الميزة. لم يكن لدي أي فكرة عما إذا كانت ستنجح ولكن بناء الجملة بدا طبيعيًا ، لقد ذهبت من أجله ، وقال لو rustc إنه موجود :)

لست مندهشًا من أنها لا تعمل ، لأن هذه الميزة التي تم توقعها بشدة لا تزال قيد التشغيل من خلال المترجم كما نتحدث (انظر على سبيل المثال # 59008 و # 58581 والعمل السابق على # 53645 الذي تم التخلي عنه لأن العلاقات العامة كانت كبيرة جدًا ، ولكن لا يزال مفتوحًا كمتعقب للإعلان عن التقدم).

ومع ذلك ، لست متأكدًا مما إذا كان يجب توقع وصول الشرائح خارج الحدود من خطوات التنفيذ الحالية. varkoryodaldevoid، يمكنك إلقاء نظرة؟

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

آسف إذا لم يكن هذا هو المكان المناسب لطرح الأسئلة ولكن لم أجد أي مكان أفضل منه. سؤالان فقط:

  1. هل يمكن أن تكون دالة واحدة ثابتة شرطية ؟ على سبيل المثال ، يمكن أن تحتوي الوظيفة على توقيعين مثل:

    const fn foo<A: const T>(x: T)  // `A` const implements `T`
    fn foo<A: T>(x: A)              // `A` implements `T` normally
    

    في هذه الحالة ، foo هو ثابت iff A: const T ؛ إذا كان A لا يطبق T ، فإنه لا يزال يفي بالحد ولكن foo لم يعد ثابتًا. من المهم أيضًا أن يكون المؤلف قادرًا على تحديد أي حد عام لأمثلة أكثر تعقيدًا (على سبيل المثال where A::Output : Bar ). ومن الأمثلة الرائعة على ذلك عملية حسابية بسيطة:

    // This only accepts types that const implement `T`
    const fn square_const<T: const Mul>(x: T) -> T {
      x*x
    }
    
    // This accepts types that implement `T` any way, but it is not const
    // This function behaves identically to `square_const`
    // But has a different signature and needs a different name
    fn square<T: Mul>(x: T) -> T {
      square_const(x)
    }
    
    let a: u8 = 5;
    let b: FooNumber = FooNumber::new();
    square_const(a); // `u8` const implements Mul
    square(b); // `FooNumber` implements `Mul` normally, so we need a separate function?
    

    أشعر بقوة أنه يجب أن تكون هناك بالتأكيد طريقة للقيام بذلك ، وأنا مندهش من عدم ذكرها في RFC (إلا إذا فاتني ذلك؟).

  2. _ [أقل أهمية]: _ هل ستكون هناك طريقة للكشف في جسم دالة ثابتة سواء كنا نعمل في وقت التجميع أو وقت التشغيل؟ أعتقد أن بعض وحدات الماكرو المشابهة لـ cfg!() ستكون امتدادًا مفيدًا ، إذا لم يكن هناك سبب آخر غير التصحيح. cfg!() حاليًا في وقت الترجمة بالفعل ، لذلك أعتقد (/ تخمين) أنه يجب أن يكون قادرًا على معرفة ما إذا كان يتم استخدام الوظيفة كدالة ثابتة أم لا حيث يتم تحديد ذلك أيضًا عند التجميع -زمن. لكن هذا أقل أهمية من سؤالي الأول.

@ المبرمج 256

  1. نعم ، راجع https://github.com/rust-lang/rfcs/pull/2632.
  2. لست متأكدًا مما إذا كان من الممكن أن يكون ذلك ممكنًا ، على الرغم من أنني لست متأكدًا من أنه ضروري في ضوء ما سبق.

@ Coder-256 كلا هذين السؤالين لا علاقة لهما بعلم الثوابت ، بل بالأحرى دوال ثابته. تستخدم الأدوية العامة للأرقام الثابتة لكونها عامة أكثر من الثوابت (على سبيل المثال foo<2>() ) بدلاً من الوظائف التي يمكن تشغيلها في وقت الترجمة. أتخيل أن هذا هو السبب في أنك لم تجد إجابات لأسئلتك في RFC 2000.

rpjohnst شكرًا لك ، لكني أعتقد أنني قد أكون غير واضح. لقد رأيت بالفعل كلا من rust-lang / rfcs # 2632 و rust-lang / rfcs # 2000 ، لكنني متأكد من أن هذا لم يرد في أي منهما. (ولكن قد أكون مخطئا؟) ما أسأل عنه هو دوال شرطية . انظر إلى الأمثلة التي كتبتها لأنه من الصعب وصفها.

yodaldevoid عفوًا ، أنت على حق ، أين أسأل هذا؟

بالنسبة لسؤال الماكرو ، أوافق على أنه لا يوجد فائدة كبيرة له الآن بعد أن أفكر فيه

ما أسأل عنه هو دوال شرطية. انظر إلى الأمثلة التي كتبتها لأنه من الصعب وصفها.

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

varkor لست مقتنعًا بأن هذا هو الحال (منذ تغير حدود السمات) ، لكنني سأطلب في rust-lang / rfcs # 2632.

تقرير الأعطال:

الشفرة:

#![feature(const_generics)]

use std::marker::PhantomData;

struct BoundedU32<const LOWER: u32, const UPPER: u32> {
    value: u32,
    _marker: PhantomData<(LOWER, UPPER)>,
}

مترجم:

thread 'rustc' panicked at 'slice index starts at 1 but ends at 0', src/libcore/slice/mod.rs:2419:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports

note: rustc 1.35.0-nightly (719b0d984 2019-03-13) running on x86_64-unknown-linux-gnu

note: compiler flags: -C codegen-units=1 -C debuginfo=2 --crate-type lib

note: some of the compiler flags provided by cargo are hidden

error: Could not compile `playground`.

To learn more, run the command again with --verbose.

Jezza : إن Generator لم تنفذ بالكامل بعد ولا يُتوقع أن تعمل. سنصدر إعلانًا عندما يحين وقت بدء تجربة #![feature(const_generics)] (والذي سيتم إعلامك به إذا كنت مشتركًا في هذه المشكلة).

varkor معلقة على، سبيل المثالJezza الصورة لديها _marker: PhantomData<(LOWER, UPPER)> - تلك نوعان const المعلمات تستخدم أنواع، لماذا لم rustc_resolve ينتج خطأ؟

نقطة جيدة: سأحقق في هذا. لاحظ أن هذه مشكلة فقط مع #![feature(const_generics)] ، لذا فهي ليست مشكلة حرجة (استخدام الثوابت غير العامة ينتج الخطأ كما هو متوقع). ربما لا تصل أبدًا إلى rustc_resolve .

~ eddyb : resolve_ident_in_lexical_scope ، لذلك أتخيل أنه من المحتمل أن يكون مرتبطًا بـ https://github.com/rust-lang/rust/issues/58307.~

تحرير: في الواقع ، ربما لا - يبدو أنه ينطبق فقط على macro_rules! .

مصغر:

#![feature(const_generics)]

struct S<const C: u8>(C);

قم بحل ICE قبل إنتاج الخطأ "النوع المتوقع ، القيمة التي تم العثور عليها".

الفهرس خارج الحدود هنا:
https://github.com/rust-lang/rust/blob/master/src/librustc_resolve/lib.rs#L3919

تنتج الليلة الحالية "المعلمة N لم يتم استخدامها أبدًا" للرمز التالي:

struct Foo<const N: usize> { }

من المناقشة السابقة اعتقدت أن التجميع يجب أن يقبل هذا الرمز. هل هو مجرد قطعة أثرية من التنفيذ غير المكتمل؟

newpavlov يجب استخدام معلمات النوع العادي ، PhantomData<n> ؟

أعتقد أنه من الممكن بالفعل القيام بـ PhantomData<[(); N]> . لست متأكدًا من أن هذا شيء نريد حقًا فرضه ، على الرغم من ذلك ، مثل AFAIU ، فإن النقطة PhantomData هي تحديد التباين ، ولا يوجد AFAIU أي فكرة عن التباين مكتوب. معلمة عامة ثابتة.

وهذا لا يعمل إلا عندما يكون N من النوع usize .

لقد قررنا أنه ليس من الضروري استخدام معلمات const أثناء مناقشة RFC والتنفيذ الحالي هو خطأ.

withoutboats هل يمكنك الإشارة إلى مكان ما ورد في RFC؟ حاولت العثور على شيء بهذا المعنى ويجب أن يكون قد فاتني.

لا أعرف ما إذا كان قد تم تضمينه في نص RFC

withoutboats هل تمانع في الإشارة إلى مكان مناقشة ذلك؟ بحثت في RFC PR ، لكنها لم تقفز في وجهي.

yodaldevoid تمت الإشارة إلى هذا التعليق سابقًا: https://github.com/rust-lang/rust/issues/44580#issuecomment -419576947. لكنه لم يكن في RFC PR ، بل كان في هذه القضية.

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

@ HadrienG2 شكرًا لك على العثور على تعليق ذي صلة.

withoutboats لم أكن أتوقع حقًا أن تذهب للبحث في كل سنوات التعليقات على هذا ، كان مجرد أمل في أن يكون لديك بالفعل في متناول اليد.

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

فيما يلي ملخص للتقدم المحرز حتى الآن في الأدوية العامة.


قبل أن يبدأ العمل على الأدوية العامة الثابتة بشكل صحيح ، كان هناك بعض إعادة الهيكلة التي يجب القيام بها. تولى jplatte المهمة مع https://github.com/rust-lang/rust/pull/45930. بعد ذلك ، بدأ jplatte العمل على التطبيق الرئيسي للأدوية الثابتة ، لكنه اكتشف أنه لم يكن لديه الوقت الكافي للمتابعة.

التقطت أنا و yodaldevoid المكان الذي توقفت فيه https://github.com/rust-lang/rust/pull/48149 ، https://github.com/rust-lang/rust/pull / 48452 ، https://github.com/rust-lang/rust/pull/48523 ، https://github.com/rust-lang/rust/pull/51880.

مع القيام بذلك ، يمكن أن يبدأ تطبيق الأدوية العامة بجدية. منذ ذلك الحين ، عملت أنا و https://github.com/rust-lang/rust/pull/58191 ، https://github.com/rust-lang/rust / pull / 58503 ، https://github.com/rust-lang/rust/pull/58581 ، https://github.com/rust-lang/rust/pull/58583 ، https://github.com/rust -lang / rust / pull / 59170 ، https://github.com/rust-lang/rust/pull/59355 ، https://github.com/rust-lang/rust/pull/59415 ، https: // github .com / rust-lang / rust / pull / 60058 ، https://github.com/rust-lang/rust/pull/60280 ، https://github.com/rust-lang/rust/pull/60284 and most مؤخرًا https://github.com/rust-lang/rust/pull/59008. (تم فصل هذه في الغالب عن


ما هو الوضع الآن؟ تعمل بعض الاختبارات العامة لـ const ومع ذلك ، لا تزال هناك اختبارات لا تعمل ، وهناك عدد من FIXME s في جميع أنحاء الكود الذي لا يزال يتعين علينا معالجته. نحن نقترب الآن ، رغم ذلك ، ونحن في مرحلة حيث توجد بعض الفاكهة المتدلية إذا كنت تريد المساعدة.

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

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

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

لقد كنت أتوقع شهورًا لهذا المنشورvarkor :) أنا لست معالج الصدأ ولكني أود التعامل مع أحد FIXME s

تهانينا jplatte و yodaldevoid وvarkor. هذه خطوة كبيرة للتخلص من السمات المخصصة Array-like في مراسيم الرياضيات.

عبر نشر...

varkor فيما يتعلق بالاختبارات ، ربما يكون من المفيد معرفة ما هو متوقع أن يعمل. على سبيل المثال ، فوجئت أن هذا لا يعمل: https://play.rust-lang.org/؟version=nightly&mode=debug&edition=2018&gist=d84ffd15226fcffe02c102edb8ae5cf1

أيضًا ، كمرجع للمهتمين بـ FIXMEs: https://oli-obk.github.io/fixmeh/

@ mark-im حاول وضع {} حدود FOO . بهذه الطريقة ستعمل.

نقلاً عن https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md :

عند تطبيق تعبير كمعامل ثابت (باستثناء المصفوفات) ، وهو ليس تعبير هوية ، يجب احتواء التعبير داخل كتلة. هذا التقييد النحوي ضروري لتجنب طلب نظرة غير محدودة عند تحليل تعبير داخل نوع ما.

يجب أن يكون {expression} ضروريًا فقط إذا لم يكن التعبير معرّفًا أو حرفيًا ، فهذا خطأ.

نقلا عن نفس RFC:

تعبير الهوية: تعبير لا يمكن تقييمه بشكل أكبر إلا باستبداله بأسماء في النطاق. يتضمن هذا كل العناصر الحرفية وكذلك جميع المعرفات - على سبيل المثال 3 ، "مرحبًا ، العالم" ، foo_bar.

@ mark-im نعم ، حاليًا لا يمكننا التمييز بين معرفات الأنواع والثوابت عند التحليل المبدئي. لقد قررنا اتخاذ القرار بشأن كيفية التعامل مع كل ذلك في المستقبل. أفترض الآن قد يكون المستقبل.

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

عمل مدهش. يسعدني تقديم المساعدة ، من خلال إصلاح بعض من FIXME ، إذا كان بإمكاني. ليس لدي الكثير من الخبرة داخل قاعدة بيانات rustc على الإطلاق ، لذلك سأبدأ في FIXME https://github.com/rust-lang/rust/blob/master/src/librustc_mir/monomorphize/item.rs# L397 ، كما يبدو أنه سيكون سهلًا.

ماذا عن الكود التالي:

trait Foo {
    const N: usize;
    fn foo() -> [u8; Self::N];
}

حاليًا ينتج عنه "عدم وجود عنصر مرتبط باسم N للنوع Self في النطاق الحالي" خطأ تجميع. هل سيتم قبول هذا الرمز بعد الانتهاء من FIXME s أم أنه سيتطلب جهدًا إضافيًا لتنفيذه؟

تضمين التغريدة

سؤال سريع ، معذرة إذا كان هذا قد تمت مناقشته بالفعل.

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

ألا يتعارض هذا مع الاتجاه الصحيح وفقًا للمبدأ الذي يأخذه Rust في جعل توقيعات الوظيفة صريحة لتجنب حدوث أخطاء تتعلق بتنفيذ الوظيفة؟ ربما أسيء فهم هذا تمامًا وأنت تتحدث عن تحليل المعلمات العامة داخل جسم الوظيفة.

ألا يتعارض هذا مع الاتجاه الصحيح وفقًا للمبدأ الذي يأخذه Rust في جعل توقيعات الوظيفة صريحة لتجنب حدوث أخطاء تتعلق بتنفيذ الوظيفة؟ ربما أسيء فهم هذا تمامًا وأنت تتحدث عن تحليل المعلمات العامة داخل جسم الوظيفة.

يتعلق الأمر بتحديد ما إذا كانت المعرفات التي تم تمريرها كمعلمات عامة إلى دالة هي ثوابت أم أنواع.

مثال:

fn greet<const NAME:&'static str>(){
    println!("Hello, {}.",NAME);
}
const HIS_NAME:&'static str="John";
greet::<HIS_NAME>();
greet::<"Dave">();

لاحظ أنه عند تحديد الوظيفة ، يجب عليك تحديد أن NAME ثابت ، ولكن عندما تسميها ، ليس من الضروري القول أن HIS_NAME ثابت داخل مشغل التوربيني ( ::< > ).

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

newpavlov أنا مندهش من أن الكود لا يعمل. إذا كان بإمكانك إرسال قضية منفصلة ، فسيكون موضع تقدير.

تضمين التغريدة

آه ، فهمتك. افترضت خطأً أن هذا يتعلق بتوقيعات النوع / الوظيفة.

لاستخدام العوامل الثابتة على أنواع المصفوفات المضمنة ، فتحت # 60466 لمشاهدة آراء الآخرين حول هذا الموضوع.

تبدو كتل Impl مكسورة تمامًا في الوقت الحالي. هل هذا متوقع في الحالة الحالية للميزة ، أم يجب فتح مشكلة أخرى حولها؟

تبدو كتل Impl مكسورة تمامًا في الوقت الحالي. هل هذا متوقع في الحالة الحالية للميزة ، أم يجب فتح مشكلة أخرى حولها؟

تحتاج إلى إضافة {} s حول N ، impl<const N: usize> Dummy<{N}> {} .

لكن نعم ، ستحصل على خطأ بشأن المعلمة غير المقيدة.

آه بفضل. نسيت شيئا عن تقويم الأسنان!

لست مندهشًا من فشلها بمجرد حلها ، نظرًا لأن هذه كانت حالة اختبار مصغرة للغاية.

... لكن نعم ، من المحتمل أن يعمل هذا:

#![feature(const_generics)]

trait Dummy {}

struct Vector<const N: usize> {
    data: [f32; N],
}

impl<const N: usize> Dummy for Vector<{N}> {}

.. ولا يزال يفشل مع E0207:

warning: the feature `const_generics` is incomplete and may cause the compiler to crash
 --> src/lib.rs:1:12
  |
1 | #![feature(const_generics)]
  |            ^^^^^^^^^^^^^^

error[E0207]: the const parameter `N` is not constrained by the impl trait, self type, or predicates
 --> src/lib.rs:9:12
  |
9 | impl<const N: usize> Dummy for Vector<{N}> {}
  |            ^ unconstrained const parameter

error: aborting due to previous error

For more information about this error, try `rustc --explain E0207`.
error: Could not compile `small-matrix`.

To learn more, run the command again with --verbose.

... وأفترض أن هذا هو ما قصده varkor بـ "مشكلات معالجة المصفوفات الخاصة بـ consts Genics" في # 60466:

#![feature(const_generics)]

fn dummy<const N: usize>() -> [f32; N] {
    [0.; N]
}

->

warning: the feature `const_generics` is incomplete and may cause the compiler to crash
 --> src/lib.rs:1:12
  |
1 | #![feature(const_generics)]
  |            ^^^^^^^^^^^^^^

error: internal compiler error: cat_expr Errd
 --> src/lib.rs:3:44
  |
3 |   pub fn dummy<const N: usize>() -> [f32; N] {
  |  ____________________________________________^
4 | |     [0.; N]
5 | | }
  | |_^

error: internal compiler error: cat_expr Errd
 --> src/lib.rs:4:5
  |
4 |     [0.; N]
  |     ^^^^^^^

error: internal compiler error: QualifyAndPromoteConstants: Mir had errors
 --> src/lib.rs:3:1
  |
3 | / pub fn dummy<const N: usize>() -> [f32; N] {
4 | |     [0.; N]
5 | | }
  | |_^

error: internal compiler error: broken MIR in DefId(0/0:3 ~ small_matrix[5b35]::dummy[0]) ("return type"): bad type [type error]
 --> src/lib.rs:3:1
  |
3 | / pub fn dummy<const N: usize>() -> [f32; N] {
4 | |     [0.; N]
5 | | }
  | |_^

error: internal compiler error: broken MIR in DefId(0/0:3 ~ small_matrix[5b35]::dummy[0]) (LocalDecl { mutability: Mut, is_user_variable: None, internal: false, is_block_tail: None, ty: [type error], user_ty: UserTypeProjections { contents: [] }, name: None, source_info: SourceInfo { span: src/lib.rs:3:1: 5:2, scope: scope[0] }, visibility_scope: scope[0] }): bad type [type error]
 --> src/lib.rs:3:1
  |
3 | / pub fn dummy<const N: usize>() -> [f32; N] {
4 | |     [0.; N]
5 | | }
  | |_^

thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:356:17
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

error: internal compiler error: unexpected panic

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports

note: rustc 1.36.0-nightly (cfdc84a00 2019-05-07) running on x86_64-unknown-linux-gnu

note: compiler flags: -C debuginfo=2 -C incremental --crate-type lib

note: some of the compiler flags provided by cargo are hidden

تضمين التغريدة
انظر # 60619 و # 60632.

أعتقد أن هذا الكود يجب أن يبني:
https://play.rust-lang.org/؟version=nightly&mode=debug&edition=2018&gist=e45b7b5e881732ad80b7015fc2d3795c

لكنها أخطاء حاليًا:

خطأ [E0119]: عمليات التنفيذ المتعارضة للسمة std::convert::TryFrom<[type error]> للنوع MyArray<_, _> :

لسوء الحظ ، يعد هذا قيدًا Try{From,Into} وليس له أي علاقة بالأدوية الثابتة. لا يمكن تنفيذها بشكل عام في كثير من الحالات: روضة الأطفال

oberien في T هو نوع أجنبي ، ولا يُعرف ما إذا كان T: Into<Foo<T>> يحمل أم لا.

في المثال الخاص بي ، [T؛ N] هو نوع محدد في libcore ، وهو #[fundamental] (لا أعرف حتى ماذا يعني هذا) ، لذلك أعتقد أن محلل السمات يعرف بالفعل [T; N]: Into<MyArray<T, {N}>> غير صحيح ، وهناك لا ينبغي أن يكون الصراع ، على ما أعتقد؟

[...] وهو #[fundamental] [...]

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

varkoryodaldevoid لذا ، انتهى بي الأمر للتو في موقف حيث S<{N == 0}> (مع S مع معامل const bool و N a const usize ) ليس S<{true}> أو S<{false}> في عين المترجم (بمعنى أنه لا يطبق نفس السمات مثل أي منهما) ، ولست متأكدًا مما إذا كان هذا خطأ أم القيد المتوقع للنموذج الأولي الحالي. هل يمكن أن تعطيني تجديدًا سريعًا لمنطق التوحيد الحالي؟

كمثال مصغر ، هذا ...

// Machinery for type level if-then-else
struct Test<const B: bool>;
trait IfFn<S, Z> { type Out; }
impl<S, Z> IfFn<S, Z> for Test<{true }> { type Out = S; }
impl<S, Z> IfFn<S, Z> for Test<{false}> { type Out = Z; }

// Returns an u8 if B is true, else an u16
fn should_be_ok<const B: bool>() -> <Test<{B}> as IfFn<u8, u16>>::Out {
    0
}

.. ينتج الخطأ التالي:

error[E0277]: the trait bound `Test<B>: IfFn<u8, u16>` is not satisfied
  --> src/lib.rs:32:1
   |
32 | / fn should_be_ok<const B: bool>() -> <Test<{B}> as IfFn<u8, u16>>::Out {
33 | |     0
34 | | }
   | |_^ the trait `IfFn<u8, u16>` is not implemented for `Test<B>`
   |
   = help: the following implementations were found:
             <Test<false> as IfFn<S, Z>>
             <Test<true> as IfFn<S, Z>>

لا أعرف في الواقع ، لكنني أعتقد أن المشكلة قد تكون أن المترجم ليس لديه المنطق ليقرر ما إذا كانت القيمة الحرفية 0 هي u8 أم u16 . جرب شيئًا مثل: 0u8 as _

هذا ليس كل شيء ، تظل رسالة الخطأ كما هي.

ولكن إذا كنت تريد إصدارًا لا يتضمن استدلالًا بنوع عدد صحيح ، فإليك تصغير أكثر ذكاءً:

struct Test<const B: bool>;
trait Not { const B: bool; }
impl Not for Test<{true }> { const B: bool = false; }
impl Not for Test<{false}> { const B: bool = true; }

fn should_be_ok<const B: bool>() -> bool {
    <Test<{B}> as Not>::B
}

لا يزال الإخفاق بسبب عدم تنفيذ Test<{B}> Not .

أهلا ! لست متأكدًا حقًا مما إذا كان من المفترض أن يعمل التوحيد في قيم ثابتة أم لا ، ولكن هناك نظام توحيد جديد في الأعمال ("الطباشير") يتم العمل عليه ولكنه ليس ما يستخدمه rustc حاليًا.
لذا فإن ما تحاول القيام به _ قد_ يجب أن ينتظر حتى يصبح الطباشير جاهزًا. وحتى ذلك الحين ، لست متأكدًا من أنه سيعمل أو من المفترض أن يعمل حتى مع الطباشير.
راجع https://github.com/rust-lang/rust/issues/48049 لمعرفة التقدم.

@ HadrienG2 هل يمكنك رفع قضية منفصلة لذلك؟ لست مندهشًا تمامًا من أن هذا لا يعمل في الوقت الحالي بسبب بعض المشكلات الأخرى التي نتطلع إليها ، ولكن هذه حالة جديدة وأود تعقبها.

carado Unification يتم إجراؤه على consts أو لن ينجح أي من هذا. لا يتم حظر الأدوية العامة على الطباشير.

@ HadrienG2 بمجرد أن يكون لدينا تخصص في الأدوية العامة الثابتة ، ستتمكن من القيام بشيء مثل

struct Test<const B: bool>;
trait Not { const B: bool; }
impl<const B: bool> Not for Test<B> { const B: bool = false; }
impl Not for Test<{false}> { const B: bool = true; }

fn should_be_ok<const B: bool>() -> bool {
    <Test<{B}> as Not>::B
}

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

yodaldevoid تم حفظه كـ https://github.com/rust-lang/rust/issues/61537 .

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

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

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

مثال:

fn factorial<const X: i32>() -> Option<i32> {
    match X {
        i if i < 0 => None,
        0 => Some(1),
        1 => Some(1),
        i => Some(factorial::<i - 1>().unwrap() + i)
    }
}

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

يجب أن تكون وظائف @ dancojocaru2000 const الطريقة المفضلة لحساب مستوى القيمة في وقت الترجمة ، على سبيل المثال https://play.rust-lang.org/؟version=nightly&mode=debug&edition=2018&gist=4994b7ca9cda0bfc44f5359443431378 ، والذي يحدث لا تعمل لأنها لم يتم تنفيذها بالكامل بعد. ولكن ليست الأدوية الجنيسة هي أيضًا const .

قد يكون المقتطف الخاص بك مشكلة لأنني لست متأكدًا مما إذا كان من المفترض أن يعمل match لوسائط const . لقد قمت أيضًا بخلط الجمع مع الضرب في الكود ، لكن هذا لا يهم كثيرًا.

أعتقد أنه يمكنك بالفعل عمل العوامل في وقت الترجمة باستخدام ترميز Peano ، والذي يظهر غالبًا كعرض توضيحي للغات وظيفية أخرى.

تجميع الوقت يحسب وظائف بسيطة

أعتقد أن الميزة الأكثر ملاءمة ستكون const fn .

نظريًا ، ستعمل التعليمات البرمجية الخاصة بك كما هي تقريبًا

#![feature(const_generics)]

fn factorial<const X: i32>() -> Option<i32> {
    match X {
        i if i < 0 => None,
        0 => Some(1),
        1 => Some(1),
        i => Some(factorial::<{X - 1}>().unwrap() + i)
    }
}

fn main() {
    println!("{:?}", factorial::<10>());
}

لكنها لا:

warning: the feature `const_generics` is incomplete and may cause the compiler to crash
 --> src/main.rs:1:12
  |
1 | #![feature(const_generics)]
  |            ^^^^^^^^^^^^^^

error: internal compiler error: src/librustc_codegen_ssa/mir/operand.rs:79: unevaluated constant in `OperandRef::from_const`

على الرغم من أنه يجب عليك حقًا استخدام نوع غير موقع:

#![feature(const_generics)]

fn factorial<const X: u32>() -> u32 {
    match X {
        0 => 1,
        1 => 1,
        _ => factorial::<{ X - 1 }>() + X,
    }
}

fn main() {
    println!("{:?}", factorial::<10>());
}

هل هناك أي مكان أكثر تنظيماً من هذه المشكلة حيث يمكنني العثور على كيفية استخدامه وأشياء أخرى؟

عادة ما يغطيها الكتاب غير المستقر ، لكن لا يوجد شيء مفيد هناك الآن. عندما تكتشف البتات ، ربما يمكنك التفكير في البدء في رسم بعض المحتوى لذلك؟

عاملي في وقت الترجمة مع ترميز Peano ،

للحصول على مثال على ذلك ، انظر صندوق النوع

نظريًا ، ستعمل التعليمات البرمجية الخاصة بك كما هي تقريبًا

عند استدعاء factorial::<0> ، سيتم ترميز _ => factorial::<{X - 1}>() * X أليس كذلك؟ لكن محاولة القيام بذلك قد يتسبب في تدفق عدد صحيح.

هل يمكنني أن أتوقع أن يتم تجميع رمز مثل هذا في المستقبل؟

#![feature(const_generics)]

trait NeedsDrop<const B: bool> { }
impl<T> NeedsDrop<std::mem::needs_drop<T>()> for T { }

fn foo<D: NeedsDrop<false>>(d: D) { }

يتعارض هذا مع تطبيق حديث لبعض المصفوفات [T; N] لـ N <= 32 كإصدارات ثابتة ، لكن الكود التالي لا يتم تجميعه على أحدث ( 4bb6b4a5e 2019-07-11 ) كل ليلة مع أخطاء مختلفة the trait `std::array::LengthAtMost32` is not implemented for `[u64; _]`

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct BigintRepresentation<
    const N: usize
>(pub [u64; N]) 
where [u64; N]: std::array::LengthAtMost32, 
   [u64; N*2]: std::array::LengthAtMost32;

على الرغم من أن ما يلي:

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct BigintRepresentation<
    const N: usize
>(pub [u64; N]) 
where [u64; N]: std::array::LengthAtMost32;

يبدو أن N*2 ليس قيمة ثابتة أو مؤهلًا صالحًا لمثل هذا القيد

shamatar N*2 يجب أن تكون محاطة بأقواس معقوفة مثل `[u64؛ {N * 2}]

أعتقد أن أخطاء "السمة غير مطبقة" تأتي من اشتقاق وحدات الماكرو التي لا تضيف الحد لـ [u64; {N*2}] ، ولكن إذا تمت إزالة المشتقات ، فهناك ICE حاليًا:

"" خطأ: خطأ داخلي في المترجم: ثابت في النوع به خطأ تم تجاهله: TooGeneric
-> src / main.rs: 5: 1
|
5 | / pub هيكلة BigintRepresentation <
6 | | const N: استخدام
7 | | > (pub [u64؛ N])
8 | | حيث [u64؛ N]: الأمراض المنقولة جنسياً :: مجموعة :: LengthAtMost32 ،
9 | | [u64 ؛ {N * 2}]: std :: array :: LengthAtMost32؛
| | ____________________________________________ ^

سلسلة الرسائل "rustc" أصيبت بالذعر عند "عدم وجود أخطاء على الرغم من إصدار delay_span_bug " ، src / librustc_errors / lib.rs: 366: 17
ملاحظة: قم بتشغيل باستخدام متغير البيئة RUST_BACKTRACE=1 لعرض تتبع خلفي.

هذا الرمز لا يجمع:

#![feature(const_generics)]

struct Foo<const X: usize>([u8; X]);

impl<const X: usize> Foo<X> {
    fn new() -> Self {
        Self([0u8; X])
    }
}
warning: the feature `const_generics` is incomplete and may cause the compiler to crash
 --> src/lib.rs:1:12
  |
1 | #![feature(const_generics)]
  |            ^^^^^^^^^^^^^^

error[E0573]: expected type, found const parameter `X`
 --> src/lib.rs:5:26
  |
5 | impl<const X: usize> Foo<X> {
  |                          ^
  |                          |
  |                          not a type
  |                          help: try using the variant's enum: `regex_syntax::ast::HexLiteralKind`

error[E0107]: wrong number of const arguments: expected 1, found 0
 --> src/lib.rs:5:22
  |
5 | impl<const X: usize> Foo<X> {
  |                      ^^^^^^ expected 1 const argument

error[E0107]: wrong number of type arguments: expected 0, found 1
 --> src/lib.rs:5:26
  |
5 | impl<const X: usize> Foo<X> {
  |                          ^ unexpected type argument

error: aborting due to 3 previous errors

npmccallum ، عليك القيام بـ Foo<{X}>

@ pengowen123 نعم ، إنها تجمع (تعطل المحول البرمجي بـ constant in type had an ignored error: TooGeneric ) بدون derive ، ولكن بعد ذلك قد يكون سؤالًا منفصلاً عما إذا كان هذا "القيد المزدوج" يكون فعالاً N <= 32 و N <= 16 لا يستخدمها المترجم.

من المحتمل ألا تعمل التعبيرات التي تشير إلى المعلمات لفترة أطول ، فالعبارات التي تشير إلى المعلمات [T; N] و Foo<{N}> تكون ذات غلاف خاص بحيث لا تحتوي على تعبيرات بذكر N فيها ، ولكن بدلاً من ذلك الرجوع مباشرة إلى المعلمة N ، متجاوزًا المشكلة الأكبر.

استخدام Self يتسبب في حدوث عطل.
حتى استبداله بـ Value<{C}> ، فإنه لا يزال يتعطل.

#![feature(const_generics)]

struct Value<const C: usize>;

impl<const C: usize> Value<{C}> {
    pub fn new() -> Self {
        unimplemented!()
    }
}

pub fn main() {
    let value = Value::new();
}

مثل # 61338 ، مصدر المشكلة هو التجميع المتزايد.

تجميع الوقت يحسب وظائف بسيطة

أعتقد أن الميزة الأكثر ملاءمة ستكون const fn .

نظريًا ، ستعمل التعليمات البرمجية الخاصة بك كما هي تقريبًا

#![feature(const_generics)]

fn factorial<const X: i32>() -> Option<i32> {
    match X {
        i if i < 0 => None,
        0 => Some(1),
        1 => Some(1),
        i => Some(factorial::<{X - 1}>().unwrap() + i)
    }
}

fn main() {
    println!("{:?}", factorial::<10>());
}

لكنها لا:

warning: the feature `const_generics` is incomplete and may cause the compiler to crash
 --> src/main.rs:1:12
  |
1 | #![feature(const_generics)]
  |            ^^^^^^^^^^^^^^

error: internal compiler error: src/librustc_codegen_ssa/mir/operand.rs:79: unevaluated constant in `OperandRef::from_const`

على الرغم من أنه يجب عليك حقًا استخدام نوع غير موقع:

#![feature(const_generics)]

fn factorial<const X: u32>() -> u32 {
    match X {
        0 => 1,
        1 => 1,
        _ => factorial::<{ X - 1 }>() + X,
    }
}

fn main() {
    println!("{:?}", factorial::<10>());
}

هذه الميزة مفيدة لي أيضًا ، const fn ليس كافيًا. أريد استخدامه لصفيف ذو أبعاد N بشرط إنهاء الأبعاد = 0.

أنا قادر على إنشاء هيكل:

#![feature(const_generics)]
struct MyArray<T: Default, const len: usize> {
    real_array: [T; len]
}

impl<T: Default, const len: usize> MyArray<T, {len}> {
    fn new() -> Self {
        return MyArray {
            real_array: [Default::default(); len]
        }
    }
}

فشل هذا لأنني لا أستطيع بالفعل تهيئة المصفوفة للأسباب التالية:

error: array lengths can't depend on generic parameters
 --> src/main.rs:9:46
  |
9 |             real_array: [Default::default(); len]
  |                                              

لقد حاولت العمل على حلها من خلال تعيين قيم ثابتة على القيمة العامة.

هذا يتخطى الخطأ أعلاه ، لكن المترجم يتعطل بعد ذلك.

error: internal compiler error: src/librustc/ty/subst.rs:597: const parameter `height/#0` (Const { ty: usize, val: Param(height/#0) }/0) out of range when substituting substs=[]

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

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

هناك بالفعل بعض الجهد هناك https://github.com/rust-lang/rust/issues/61415.

آمل ألا يضيع أحد وقته في التأكد من أن هذه الأمثلة السخيفة تعمل.

بعض الناس يفعلون ذلك ، لا أرى أي مشكلة في ذلك ؛)

هذا هو السبب الوحيد الذي يجعلني لا أستخدم الصدأ.

هذا هو السبب الأقل إثارة للاهتمام الذي رأيته مقتبسًا عن شخص لا يستخدم الصدأ. هل أنت متأكد من أنك تقول الحقيقة؟

لكن يجب أن تكون التعبيرات الصحيحة البسيطة كافية

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

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

آمل ألا يضيع أحد وقته في التأكد من أن هذه الأمثلة السخيفة تعمل.

لا أحد ، miri أقوى بكثير من C ++ constexpr .
ولا أحد يعمل على أي شيء خيالي مثل اشتقاق N = M من N + 1 = M + 1 .

معظم هذه الأخطاء لا تتعلق بالتعبيرات الموجودة فيها ، إنها تتعلق بنظام الكتابة وكيفية تفاعل const generics مع جميع الميزات الأخرى.
كانوا لا يزالون هناك إذا كان كل ما لديك هو const أدوية عامة وأرقام حرفية صحيحة.

بالمناسبة ، أعتقد أن الخطأ "لا يمكن أن تعتمد أطوال المصفوفة على معلمات عامة" لتعبيرات [expr; N] ليست هناك حاجة ، يمكننا استخدام نفس الحيلة التي نستخدمها لأنواع [T; N] ، وسحب خارج N بدون تقييمه كتعبير.

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

تحرير: لدي قدر لا بأس به من الخبرة في مجال البرمجيات بشكل عام.

varkor ، لقد كنت أبحث عن شيء مفيد rustc ، وأود أن أقدم المساعدة. أيضًا ، شكرًا لصراحتك بشأن قدرتك على تخصيص الوقت لذلك!

varkor ، أنا في الواقع أتابع التعليق أعلاه ، لذا إذا كان لديك أي نصيحة ، فأنا آذان صاغية! لا تتردد في إحالتي إلى قناة اتصال أخرى أيضًا.

شيء واحد يمكننا القيام به الآن ، لقد أدركت للتو السماح بتعبيرات Foo::<{...}> / [expr; ...] للإشارة إلى المعلمات العامة (في الجزء ... ).

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

ومع ذلك ، أشعر بالقلق من أن وجود مثل [(); [0; 1][0]] في التوقيع قد ينكسر ، لذلك ربما نحتاج إلى تشغيل فوهة البركان على أي حال (وفي الوقت الحاضر يستغرق ذلك إلى الأبد).

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

cchameerabbasi ، ranweiler

أسئلة حول كونست جنرالس:

  1. أين يمكنني العثور على الوثائق (حتى لا أضطر لطرح الأسئلة هنا)
  2. ما هي القيود الموجودة في هذه اللحظة على استخدام معلمة const من النوع التعسفي؟
  3. ما هي الميزات المهمة للأدوية const generics التي لم يتم تنفيذها / تعطل المترجم؟

ملاحظة (المساهمون:) شكرًا جزيلاً على العمل على هذه الميزة.

لا تزال ملفات const-Genics قيد التطوير ، لذا لا توجد أي مستندات رسمية عليها حتى الآن. لست متأكدًا جدًا من السؤالين الآخرين. عند آخر مرة استخدمت فيها عناصر const-Generic ، تعطلت عندما حددت بعض المعلمات العامة لـ const ، ولكن مر ما يقرب من شهر منذ أن فعلت أي شيء معها ، لذا ربما تغيرت الأشياء منذ ذلك الحين.

ولا أحد يعمل على أي شيء خيالي مثل اشتقاق N = M من N + 1 = M + 1 .

سيكون هذا مفيدًا جدًا للحصول على حل لقيود النوع هذه. على سبيل المثال ، عند تنفيذ إضافة إذا كان عدد بتات N ، يجب أن يكون حجم الإرجاع (N + 1) لحساب بت الفائض. عندما (على سبيل المثال) يتم إعطاء رقمين من 5 بتات ، يجب على المحلل التحقق من أن N + 1 = 6 . نأمل أن يتم تثبيت هذا في قائمة الأدوية العامة لاحقًا :)

@ flip111 نعم ، أعتقد أن الخطة هي إضافة هذا لاحقًا ، لكن هذا النوع من قيود التعبير العام معقد للغاية ويصعب تنفيذه. لذلك قد لا نراهم لبضع سنوات على الأقل.

لكي نكون صادقين ، فإن حل هذه الأنواع من المشكلات القائمة على القيود يشبه إلى حد كبير وظيفة Prolog. ربما يكون التحميل على محرك الطباشير خيارًا؟ Afaik يحل السمات ، رغم ذلك ، أليس كذلك؟

بالمناسبة أنا أحب الموضوع ، على الرغم من أنني لا أستطيع المساعدة في هذا الصراف الآلي. شكرًا لكل من يعمل في Const Generics على وقتك والتزامك. 💐

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

أنا قادر على إنشاء هيكل:

#![feature(const_generics)]
struct MyArray<T: Default, const len: usize> {
    real_array: [T; len]
}

impl<T: Default, const len: usize> MyArray<T, {len}> {
    fn new() -> Self {
        return MyArray {
            real_array: [Default::default(); len]
        }
    }
}

فشل هذا لأنني لا أستطيع بالفعل تهيئة المصفوفة للأسباب التالية:

error: array lengths can't depend on generic parameters
 --> src/main.rs:9:46
  |
9 |             real_array: [Default::default(); len]
  |                                              

واجهت نفس المشكلة ، ولكن وجدت حلاً باستخدام MaybeUninit :
https://play.rust-lang.org/؟version=nightly&mode=release&edition=2018&gist=3100d5f7a4efd844954a6fa5e8b8c526
من الواضح أنه مجرد حل بديل للحصول على مصفوفات مهيأة بشكل صحيح ، لكن بالنسبة لي هذا يكفي حتى يتم توفير طريقة مناسبة.
ملاحظة: أعتقد أن الكود يجب أن يعمل دائمًا على النحو المنشود ، ولكن إذا وجد شخص ما خطأ في استخدام المادة غير الآمنة ، فسأكون سعيدًا بإصلاحه.

raidwas أنت تقوم بإسقاط ذاكرة غير مهيأة عند استخدام عامل التشغيل = لتهيئة ذاكرة غير مهيأة. افعل هذا بدلاً من ذلك ،

https://play.rust-lang.org/؟version=nightly&mode=debug&edition=2018&gist=5d962ce7c553e850030240244608ec00

KrishnaSannasi شكرًا ، التقاط جيد: D (من الناحية الفنية لم أسقط ذاكرة غير مهيأة لأنني

من الناحية الفنية ، فإن إسقاط حتى العوامات غير محدد ، لكنه ليس قابلاً للاستغلال في الوقت الحالي.

من الناحية الفنية ، فإن إسقاط حتى العوامات غير محدد ، لكنه ليس قابلاً للاستغلال في الوقت الحالي.

كنت أتوقع أن إسقاط أي نوع Copy ، حتى الأنواع غير المهيأة ، يعد أمرًا محظورًا. ربما هذا يستحق التغيير.

من الناحية الفنية ، فإن إسقاط حتى العوامات غير محدد ، لكنه ليس قابلاً للاستغلال في الوقت الحالي.

كنت أتوقع أن إسقاط أي نوع Copy ، حتى الأنواع غير المهيأة ، يعد أمرًا محظورًا. ربما هذا يستحق التغيير.

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

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

تعطل إذا استخدمت _aliases تشير إلى الكتابة باستخدام const-param_ من صندوق آخر (تبعية).

على سبيل المثال:

  • قفص أ ، ليب
    "" #! [crate_type = "lib"]

    ! [ميزة (const_generics)]

نوع حانة الاسم المستعار= الهيكل؛
هيكل حانة(T) ؛

- crate B

قفص خارجي - a ؛
استخدام crate_a :: الاسم المستعار ؛

pub fn inner_fn (v: Alias) {}
""
سجل الأعطال (44580) .txt

@ fzzr- يبدو مثل # 64730

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

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

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

mqudsi هل يمكنك إعطاء مثال؟ هناك بالفعل خطط وعمل تأسيسي مستمر لجعل التقييم الثابت أكثر قوة. هذا متعامد مع الأدوية الجنيسة ، رغم ذلك.

ما أعنيه هو ، إذا كنت تريد إعادة بناء كود محلل نموذجي مثل ما يلي لإعادة استخدامه:

let mut result: u32 = 0;
let mut digits = 0;
while digits < max_digits && src.has_remaining() {
    match src.get_u8() {
        d<strong i="6">@b</strong>'0'..=b'9' => {
            result = result*10 + (d - b'0') as u32;
            digits += 1;
        },
        b'>' => match result {
            0..=191 => break, // valid range
            _ => return Err(DecoderError::OutOfRange),
        },
        _ => return Err(DecoderError::Malformed)
    }
}

يمكنك عادةً نقلها إلى دالة ، باستثناء ما يلي لن يعمل لأن بعض القيم المستخدمة في مطابقة النمط أصبحت متغيرات:

#[inline(always)]
fn read_str_digits<B: bytes::buf::Buf>(src: &mut B, stop_word: u8, 
    max_digits: u8, min_value: u32, max_value: u32) -> Result<u32, DecoderError> {
    let mut result: u32 = 0;
    let mut digits = 0;
    while digits < max_digits && src.has_remaining() {
        match src.get_u8() {
            d<strong i="10">@b</strong>'0'..=b'9' => {
                result = result*10 + (d - b'0') as u32;
                digits += 1;
            },
            stop_word => match result {
                min_value..=max_value => break, // valid range
                _ => return Err(DecoderError::OutOfRange),
            },
            _ => return Err(DecoderError::Malformed)
        }
    }

    ...
}

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

#[inline(always)]
fn read_str_digits<const MinValue: u32, const MaxValue: u32, const StopWord: u8, B: bytes::buf::Buf>
(src: &mut B, max_digits: u8) -> Result<u32, DecoderError> {
    let mut result: u32 = 0;
    let mut digits = 0;
    while digits < max_digits && src.has_remaining() {
        match src.get_u8() {
            d<strong i="14">@b</strong>'0'..=b'9' => {
                result = result*10 + (d - b'0') as u32;
                digits += 1;
            },
            StopWord => match result {
                MinValue..=MaxValue => break, // valid range
                _ => return Err(DecoderError::OutOfRange),
            },
            _ => return Err(DecoderError::Malformed)
        }
    }

    ...
}

اعتبارًا من اليوم ، حتى هذا الرمز لن يعمل لأن المترجم لا يكتشف القيم العامة الثابتة لتكون ثوابت صالحة للاستخدام في نمط ، ولكن من الواضح أن هذا غير صحيح ويجب معالجته قبل أن يتمكن RFC 2000 من الهبوط. لا تفهموني خطأ ، لقد كنت أقاتل من أجل الثوابت العامة لسنوات ولدي علاقات عامة جاهزة للذهاب لعشرات الصناديق الرئيسية (لا أطيق الانتظار لجعل المنطقة الزمنية في chrono a const عامة و توحيد جميع أنواع DateTime المختلفة) ، لكن imho إذا أصبح من الممكن إساءة استخدام أدوات إنشاء المعاملات لتزوير وسيطات ثابتة (حيث نعني بكلمة "const" ما نعنيه حقًا "حرفيًا") ، فحينئذٍ ستشهد انتشارًا واسعًا إساءة استخدام ذلك.

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

fwiw ، هذه هي الطريقة التي أتخيل بها نسخة وسيطة const لتبدو كما يلي:

#[inline(always)]
fn read_str_digits<B: Bytes>(src: &mut B, min_value: const u32, 
    max_value: const u32, stop_word: const u8, max_digits: u8) -> Result<u32, ()> {
    let mut result: u32 = 0;
    let mut digits = 0;
    while digits < max_digits && src.has_remaining() {
        match src.get_u8() {
            d<strong i="23">@b</strong>'0'..=b'9' => {
                result = result*10 + (d - b'0') as u32;
                digits += 1;
            },
            stop_word => match result {
                min_value..=max_value => break, // valid range
                _ => return Err(()),
            },
            _ => return Err(())
        }
    }

    ...
}

سيكون عمليا متطابقة مع علم الثوابت ولكن بالنسبة إلى دلالات الألفاظ.

يمكنك عادةً نقلها إلى دالة ، باستثناء ما يلي لن يعمل لأن بعض القيم المستخدمة في مطابقة النمط أصبحت متغيرات:

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

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

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


  • قام @ skinny121 بعمل رائع في الشهر الماضي لإصلاح العديد من المشكلات المعلقة باستخدام أدوية const Generator:

    • توسيع مجموعة الاختبار (https://github.com/rust-lang/rust/pull/60550)

    • إصلاح مشكلات استدلال النوع (https://github.com/rust-lang/rust/pull/64679 ، https://github.com/rust-lang/rust/pull/65579)

    • دعم المزيد من الأنواع في الأدوية العامة ، بما في ذلك السلاسل والشرائح (https://github.com/rust-lang/rust/pull/64858) والمؤشرات (https://github.com/rust-lang/rust/pull/64986 ) (على الرغم من ملاحظة أنه من المحتمل ألا يتم استقرارها على الفور جنبًا إلى جنب مع باقي الأدوية العامة الثابتة ، لأنها غير مدعومة في RFC الأصلي )

    • إصلاح مشكلات التشخيص مع الأدوية الثابتة (https://github.com/rust-lang/rust/pull/65154 ، https://github.com/rust-lang/rust/pull/65579)

    • إصلاح عدد من المشكلات المتعلقة باستخدام الصناديق المتقاطعة للأدوية (https://github.com/rust-lang/rust/pull/65365)

  • قامeddyb بإصلاح بعض المشكلات المتعلقة بتقييم const التي تؤثر على الأدوية العامة (https://github.com/rust-lang/rust/pull/63497)
  • قامmatthewjasper بإصلاح بعض المشكلات المتعلقة باستخدام Genics في وحدات الماكرو (https://github.com/rust-lang/rust/pull/63083)
  • قامdavidtwco بإصلاح مشكلة تتعلق
  • قامGuillaumeGomez بإصلاح عرض الأدوية العامة الثابتة في Rustdoc (https://github.com/rust-lang/rust/pull/61605)
  • أصلحvarkor بعض مشكلات الاستدلال على النوع (https://github.com/rust-lang/rust/pull/61570 ، https://github.com/rust-lang/rust/pull/60742 ، https: // github. com / rust-lang / rust / pull / 60508) ، وهي مشكلة تقيد الأماكن التي يمكن استخدام أدوات إنشاء الصور (https://github.com/rust-lang/rust/pull/60717) والعديد من أعطال المترجم (https: / /github.com/rust-lang/rust/pull/61380 ، https://github.com/rust-lang/rust/pull/61333 ، https://github.com/rust-lang/rust/pull/60710 )

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

لقد بدأنا أيضًا في استخدام عوامل const Genics داخل المترجم نفسه: تستخدم تطبيقات سمة المصفوفة الآن عوامل const Genics بفضل عمل @ crlf0710 و scottmcm (https://github.com/rust-lang/rust/pull/60466، https : //github.com/rust-lang/rust/pull/62435) ، مما أدى إلى تحسينات في الأداء ، والذي سيسمح لنا أيضًا بإلغاء تقييد عمليات تنفيذ سمات الصفيف في المستقبل (عند استقرار العوامل الثابتة). استخدم Centril نفس الأسلوب لتحسين VecDeque (https://github.com/rust-lang/rust/pull/63061).


تم إصلاح العديد من الأخطاء الشائعة بشكل خاص مع الأدوية العامة الثابتة في الأشهر القليلة الماضية. يبحثnikomatsakis عن التطبيع البطيء ، والذي يجب أن يصلح مجموعة من المشكلات المتبقية ، بينما يبحث jplatte في إصلاح توضيح معلمات const من معلمات النوع (لذلك لن تضطر بعد الآن إلى كتابة {X} مقابل حجة const).

أود أيضًا أن أشكر eddyb على كل ما قدموه من توجيه ومراجعة

لا يزال هناك عدد كبير من المشكلات الأخرى التي يجب معالجتها ، وكما في السابق ، يمكننا استخدام كل المساعدة التي يمكننا الحصول عليها - إذا كنت مهتمًا بمعالجة أي من المشكلات المتبقية ، فلا تتردد في الاتصال بي بشأن المشكلة أو Discord أو Zulip للحصول على مؤشرات حول البدء.

mqudsi @ mark-im هل سيكون من المناسب تمديد البديل النحوي الحالي للأدوية العامة ، impl Trait في موضع الوسيطة ، إلى الأدوية العامة؟ هذا هو بناء الجملة mqudsi المقترح لحالة الاستخدام هذه.

أنا شخصياً أعتقد أن هذا سيحسن قابلية قراءة مثل هذه الحالات ، لكني أرى مشكلة واحدة: يتم استخدام الأدوية الجنيسة العادية لتمرير البيانات ، لذا فهي مرتبطة بالحجة. ليس هذا هو الحال بالنسبة للأدوية الثابتة ، فكيف يمكنك تجاوزها؟ ادعي أنها الحجج؟
في حالة impl Trait في موضع الوسيطة ، لا يمكن أيضًا استخدامه مع بناء الجملة التوربيني. بالنسبة إلى الوسيطة const ، سيكون معكوسًا. قد يكون هذا محيرا.

لست متأكدًا مما إذا كانت الفوائد تفوق "الغرابة" هنا ، لكنني أردت مشاركة أفكاري على أي حال.

تذكرت بشكل غامض مناقشة حول هذا من قبل ، والآن وجدته: https://internals.rust-lang.org/t/pre-rfc-const-function-arguments/6709

@ PvdBerg1998 التي تبدو فكرة سيئة للغاية. لا أفهم حقًا فكرة أن <…> عبارة عن بناء جملة صعب القراءة. هناك احتمالان:

  1. تعتقد ، كما أفعل ، أنه ليس من الصعب القراءة ، حتى مع وجود عدة قيود.
  2. هل تعتقد أنه من الصعب قراءتها: فربما يكون الحل هو وضعها في عبارة where ؟

قارن الآن مع ما قبل RFC المرتبط أعلاه. سيكون إدخال _tag_ (بمعنى نظام النوع) مباشرة في موضع وسيطات الوظيفة ، أي الارتباطات المتغيرة لجسم الوظيفة.

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

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

let r = _mm_blend_ps::<{2 * C}>(a, b);
let r = _mm_blend_ps(a, b, 2 * C);

السطر الثاني طبيعي في رأيي أكثر من السطر الثاني. مثال آخر هو إنشاء المصفوفة: MatrixF32::new(3, 3) مقابل MatrixF32::new::<3, 3>() . لا أوافق بشدة على أن هذه الوظيفة ستكون "مربكة للغاية". بالنسبة للمستخدم ، لا يعدو كونه متطلبًا إضافيًا لوسيطة دالة. يمكننا بالفعل محاكاة وسيطات const عبر وحدات الماكرو (انظر مضمون SIMD داخل std ) ، لكنها قبيحة وغير فعالة.

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

أعتقد أن مناقشة الحجج الثابتة هي خارج الموضوع هنا ، لذا ربما لا ينبغي أن تستمر هنا.

أحد الأشياء التي تفصل بين الوسيطات const الوسيطات impl Trait (التي ذكرها @ PvdBerg1998 ) هو أنها عبارة عن وسيطات ، مع كل ما يعنيه ذلك بالنسبة للاستدلال بالنوع.

لا يمكنك تمرير نوع نفسها حجة، ولكن يمكنك تمرير قيمة، وترك وظيفة يستنتج حججها العامة CONST من الحجج قوسين طبيعية لها من المعقول تماما.

هذا شائع إلى حد ما في C ++ ، على سبيل المثال:

template <typename T, size_t N>
size_t length(T (&array)[N]) {
    return N;
}

وهذا يختلف بمهارة من مجرد قبول المعلمة CONST وdesugaring إلى معلمة العامة CONST ( fn foo(const N: usize) -> fn foo<const N: usize>() ). إنه أقرب إلى تقييد معلمة بمعامل ثابت عام ، ثم استنتاج هذه الوسيطة العامة الثابتة من الوسيطة. لذلك قد يبدو مثال المصفوفة أعلاه كما يلي:

impl<const W: usize, const H: usize> MatrixF32<W, H> {
    fn new(w: usize<W>, h: usize<H>) -> Self { .. }
}

... حيث usize<X> عبارة عن بناء جملة مكون من أجل "a usize بقيمة X ." (وبالمثل ، قد ترغب في الحصول على usize<X..Y> للأنواع المتباينة ، والتي تمت مناقشتها في سياق تعميم NonZero .)

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

fn new(const W: usize, const H: usize) -> MatrixF32<W, H> { .. }

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

نظرًا لأنني مهتم بأنظمة الكتابة ، فإن هذا الاقتراح يتعارض مع الكثير من المبادئ السليمة والعقلانية. لا تريد خلط القيم والأنواع. لأنه ، نعم ، N (ملاحظة لم أقل usize ، قلت N ) ، على الرغم من أنك تعتقد أنها قيمة ، فهي أقرب إلى النوع من قيمة. كمبرر منطقي ، لا تمتلك Haskell أنواعًا ثابتة ولكن لديها DataKinds ، مما يسمح برفع منشئي البيانات العاديين كأنواع:

foo :: Integer -> Integer
foo 0 -- 0 has type Integer

-- but
data P (a :: Integer)

type MyP = P 10 -- 10 has kind Integer, which “value” is the 10 type

وبالتالي:

fn foo<const X: usize>()

هنا ، X أقرب إلى النوع من القيمة.

أيضا ، أنا أهتم بأحادية الشكل. إذا قرأت هذا:

let x = foo(12, "Hello, world!", None);

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

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

ربما أخطأت في قراءتي ، لقد قلت على وجه التحديد " const وسيطات ... هي وسيطات " ، وليس " const generics." يعد مثال Rust الأول الخاص بي مكافئًا تمامًا لـ DataKinds ( usize<N> هو الإصدار على مستوى النوع من N ). لا توجد مشكلة هنا فيما يتعلق بصحة النوع - فأنا لا أجادل من حيث الحدس ولكن عن طريق القياس على الأنظمة القائمة والراسخة وأنظمة الصوت.

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

(وأنا في حيرة شديدة من ادعائك بأنني أخلط بين المعايير والحجج ، وكنت حريصًا على التمييز بينها).

أفهم ما تقصده ولكني ما زلت أشعر بقلق شديد. نظرًا لأن _argument_ تم تمييزه بعلامة _const_ ، فهذا يعني أنه لا يمكنك تمريرها _a value_ ، أثناء التحدث. أنت بحاجة لتمريرها _قيمة ثابتة_ ، والتي سيتم تعيينها إلى _const عام_. بالمناسبة ، لم تذكرها هنا ولكن هذا مجرد تطبيق من نوع سينغليتون_ إذا كنت تفكر في 10 كنوع: قيمته الوحيدة الممكنة هي 10 .

نظرًا لأنني كنت ضد السمة الضمنية في موقف النقاش ، فأنا ضد ذلك أيضًا (وستعرف سبب قدرتنا على المقارنة هنا). عدة نقاط:

  1. لا أعتقد أنه ضروري بينما تضيف الأدوية الوراثية الكثير من القيم.
  2. نظرًا لأنها تشبه الأنواع ، يجب أن تنتمي إلى مكان وجود الأنواع ، وليس مكان وجود المتغيرات.
  3. أود حقًا أن أعرف لماذا يعتقد بعض الناس أن <…> أصعب من (…) ، لا سيما بالنظر إلى struct مقابل fn . حاليًا ، يوجد لدى struct فقط <…> و fn كلاهما ، لأنه يمكن تعيين المعلمات على كلاهما.
  4. ما لم يعجبني حقًا باستخدام سمة ضمنية في موضع مناقشة هو حقيقة أنه من الصعب معرفة ماهية الوظيفة التي تم بالفعل تعيين المعلمات عليها. عندما تقرأ foo<A, B> ، فأنت تعلم أن هناك معلمتين ستؤديان إلى تعريف الوظيفة وتنفيذها.

أشعر بما تريد أن تفعله هنا. foo(1, 3) أفضل من foo<3>(1) ، لكن ليس بالنسبة لي. والسبب في ذلك هو أن foo(1, 3) يجب أن يقبل الوسيطة الثانية لتكون قائمة على وقت التشغيل وأن الاقتراح الذي تقدمه يمنعه. يمكنني رؤية التطبيقات ، مع ذلك ، خاصةً مع المصفوفات ، لكني حاليًا لا أحب الشكل الذي تبدو عليه. سأكون أكثر من ذلك بكثير لحل يقول "إذا كانت الوسيطة هي const ، فيمكننا استنتاج نوع متغير / عام ثابت.

fn foo<const N: usize>(a: usize, b: usize | N);

هذا مجرد بناء جملة تخيلي توصلت إليه لشرح وجهة نظري: إذا مررت b كقيمة ثابتة ، N = b وينتهي بك الأمر بصيغة لطيفة:

foo(1, 3)

إذا لم يكن b قيمة ثابتة ، فيجب عليك تمرير N صراحة:

foo<3>(1, x)

أيضًا ، ماذا سيكون بناء الجملة لهذا ، مع اقتراحك:

fn foo<const N: usize>(x: [f32; N]);
fn new(const W: usize, const H: usize) -> MatrixF32<W, H> { .. }

يقودنا إلى التساؤل حول العناصر المرتبطة ، باختصار ، new() هي وظيفة مرتبطة ، ويجب أن تكون مرتبطة بنوع ملموس ، العناصر العامة لـ const لها دلالات مثل "هذا النوع له هذه المعلمة ..." ، أي النوع التابع. لذلك ، لا ينبغي أن يحتوي new() في السياق على أي وسيطات. يجب أن يبدو استخدام التوضيح مثل Type<32>::new() . وبالطبع يجب أن تكون جميع الحجج المتعلقة بالأدوية العامة قابلة للنقاش.

أشعر بما تريد أن تفعله هنا. foo (1، 3) يبدو أفضل بالنسبة لك من foo <3> (1) ، لكن ليس بالنسبة لي. والسبب في ذلك هو أن foo (1 ، 3) يجب أن يقبل الوسيطة الثانية لتكون قائمة على وقت التشغيل وأن الاقتراح الذي تقدمه يمنعه.

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

كل ما أحصل عليه هو الاتصال الدلالي الذي يرسمه الاستدلال بين معلمات مستوى القيمة ومعلمات مستوى النوع. لا توجد علاقة بـ impl Trait - كانت وجهة نظري ، مرة أخرى ، هي التمييز بين الحجج الثابتة من impl Trait ، على وجه التحديد لتفادي هذا النوع من القلق غير المنتج.

أيضًا ، ماذا سيكون بناء الجملة لهذا ، مع اقتراحك:

fn foo<const N: usize>(x: [f32; N]);

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

في cppcon ، كان هناك حديث عن معلمات دالة constexpr ، والتي تبدو مشابهة لما يتحدث عنه @ PvdBerg1998 ويبدو تمامًا مثل الخيط الداخلي الذي يرتبط به @ mark-im. يبدو أنه تم استقباله بشكل جيد هناك.

تبدو فكرة جيدة ، ولكن يجب العمل عليها بعد الانتهاء من التنفيذ الأولي للأدوية الثابتة

CppCon 2019: David Stone - إزالة Metaprogramming من C ++ ، الجزء 1 من N: معلمات دالة constexpr

تحرير: تم ذكر هذا في هذا الموضوع ، وهنا الورقة ذات الصلة لمعلمات دالة constexpr
https://github.com/davidstone/isocpp/blob/master/constexpr-parameters.md

أود أن أطلب أن نحتفظ بمناقشة مثل هذا التغيير النحوي الهام إما لخيط في الأجزاء الداخلية أو قضية (أو تعديل العلاقات العامة) في RFCs repo. قسم التعليقات الخاص بهذه المشكلة طويل جدًا بالفعل ويبدو أن بناء الجملة المعني غير ضروري لـ MVP القابل للاستخدام من الأدوية العامة الثابتة.

إذا استطعنا نقل التعليقات فربما سنفعل. قد نرغب في قفل المشكلة على أعضاء فريق @ rust-lang وإخفاء جميع التعليقات الخارجية؟

يجب أن تتم جميع مناقشات التصميم في RFC repo ويجب أن تكون جميع تقارير الأخطاء في مشكلات منفصلة.

cc @ rust-lang / moderation هل هناك سابقة للقيام بذلك؟

يمكنك _ تحويل_ تعليق على مشكلة ، لكن لا يمكنك نقل التعليقات. الإغلاق جيد ، وسأخفي فقط تعليقات الموضوع.

مع بداية العام الجديد ، اعتقدت أنه سيكون من الجيد تقديم تحديث آخر حول ما نحن فيه الآن مع الأدوية الثابتة. لقد مر أكثر من عامين بقليل منذ أن تم قبول RFC للأدوية الثابتة . في السنة الأولى (تقريبًا 2018) ، تم بذل سلسلة من جهود إعادة البناء الكبيرة لتسهيل الأدوية البديلة عن طريق تحسين التعامل مع المعلمات العامة بشكل عام في جميع أنحاء المترجم. في السنة الثانية (تقريبًا 2019) ، بدأ العمل على تطبيق الأدوية العامة الثابتة نفسها: أولاً عن طريق الحصول على الحد الأدنى من العمل ، ثم إبطاء تحسين تكامل الميزة. بدأ الناس أيضًا في تجربة استخدام العوامل الثابتة في المترجم نفسه. توجد أوصاف أكثر تفصيلاً لهذه الجهود في أول نشرتي تحديث: [1] ، [2] .


كان هناك تقدم جيد في الشهرين الماضيين منذ التحديث الأخير.

  • @ skinny121 :

    • تم إصلاح مشكلة كسر الأدوية العامة لـ const تحت التجميع المتزايد وعبر الصناديق (https://github.com/rust-lang/rust/pull/65652)

    • تم إصلاح الخلل في الاستدلال النوعي الذي يؤثر على العوامل العامة الثابتة في التشخيص (https://github.com/rust-lang/rust/pull/65579)

    • إعادة تشكيل الواجهة لتقييم const (https://github.com/rust-lang/rust/pull/66877)

  • نفذ yodaldevoid توضيحًا لنوع ومعلمات const بحيث لا تحتاج معلمات const إلى أن يتم تغليفها في {} (https://github.com/rust-lang/rust/pull/66104)
  • قامeddyb بإصلاح استخدام Generics كأطوال مصفوفة ، بمجرد تنفيذ التطبيع البطيء (https://github.com/rust-lang/rust/pull/66883)
  • varkor :

    • تم تنفيذ التحقق من structural_match لمنع الأنواع ذات التحقق من المساواة المخصص من استخدامها كأدوية ثابتة (https://github.com/rust-lang/rust/pull/65627)

    • تم تصحيح بعض التشخيصات لمراعاة الأدوية العامة الثابتة (https://github.com/rust-lang/rust/pull/65614)

    • أجرى عمليات إعادة بناء مختلفة وإصلاح الاستدلال على الكتابة (https://github.com/rust-lang/rust/pull/65643، https://github.com/rust-lang/rust/pull/65660، https: // github. com / rust-lang / rust / pull / 65696)

شكراً جزيلاً لكل من كان يساعد في الأدوية الجنيسة!


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

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

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

نحن الآن أكثر من نصف الطريق خلال العام ، لذلك سألخص بإيجاز العمل الجاري. كان هناك الكثير من الأشخاص الذين شاركوا في تحسين دعم الأدوية العامة في الأشهر الستة الماضية ، لذا نشكرك على كل من ساعد بطريقة ما! أود بشكل خاص أن أشكر @ skinny121 و lcnr ، اللذين عالج كلاهما بعض الميزات الكبيرة التي تفتقر إليها الأدوية العامة الثابتة لفترة من الوقت: التطبيع البطيء للثوابت ودعم حجة const في استدعاءات الطريقة ، بالإضافة إلى إصلاح العديد من الأخطاء الصعبة. جهودهم واضحة من الملخص أدناه.

يتم الآن استخدام العناصر العامة لـ Const في عدة أماكن في جميع أنحاء المترجم ، وهناك بالفعل تجارب مع السمات والوظائف التي تستخدم عوامل const ، على سبيل المثال slice::array_chunks و IntoIterator و FromIterator مقابل [T; N] (https://github.com/rust-lang/rust/pull/65819 ، https://github.com/rust-lang/rust/pull/69985). يتم أخيرًا أيضًا إعداد حد الطول 32 لتطبيقات سمات الصفيف للإزالة .

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


  • @ skinny121 :

    • تم تنفيذ الإصدار الأول من التطبيع البطيء (https://github.com/rust-lang/rust/pull/68505 ، https://github.com/rust-lang/rust/pull/69181 ، https: // github. com / rust-lang / rust / pull / 67717 ، https://github.com/rust-lang/rust/pull/67890)

    • أداء محسّن (https://github.com/rust-lang/rust/pull/68118)

    • تم إصلاح الأخطاء المختلفة (https://github.com/rust-lang/rust/pull/68143)

  • lcnr :

    • تمت إضافة دعم لعوامل ثابتة صريحة في وسيطات النوع للطرق (https://github.com/rust-lang/rust/pull/74113)

    • إكمال أول تطبيق للتطبيع البطيء للثوابت (https://github.com/rust-lang/rust/pull/71973) مع @ skinny121

    • تمت إضافة نسالة مقابل unused_braces (https://github.com/rust-lang/rust/pull/70081)

    • تم إصلاح المشكلة المتعلقة بالأدوية العامة لـ const في الأنماط (https://github.com/rust-lang/rust/pull/70562)

    • حظر dyn Trait للمعلمات العامة لـ const (https://github.com/rust-lang/rust/pull/71038)

    • طباعة جميلة محسنة (https://github.com/rust-lang/rust/pull/72052)

    • تم إصلاح الأخطاء المختلفة (https://github.com/rust-lang/rust/pull/70032 ، https://github.com/rust-lang/rust/pull/70107 ، https://github.com/rust- lang / rust / pull / 70223 ، https://github.com/rust-lang/rust/pull/70249 ، https://github.com/rust-lang/rust/pull/70284 ، https: // github. com / rust-lang / rust / pull / 70319، https://github.com/rust-lang/rust/pull/70541، https://github.com/rust-lang/rust/pull/72066، https: //github.com/rust-lang/rust/pull/74159)

    • إعادة بيع ديون (https://github.com/rust-lang/rust/pull/70478)

    • الاختبارات المضافة (https://github.com/rust-lang/rust/pull/74392 ، https://github.com/rust-lang/rust/pull/74445)

  • eddyb :

    • تم إصلاح المشكلات المتعلقة بالأدوات العامة لـ const بأطوال المصفوفات (https://github.com/rust-lang/rust/pull/70452)

    • طباعة جميلة محسنة (https://github.com/rust-lang/rust/pull/71232)

    • معالجة محسّنة للأخطاء (https://github.com/rust-lang/rust/pull/71049)

    • إعادة بيع ديون (https://github.com/rust-lang/rust/pull/70164)

  • @ Aaron1011 : خطأ ثابت في استخدام الأدوية العامة لـ const عبر
  • petrochenkov : المشكلات التي تم حلها مع
  • yodaldevoid : تم حل مشكلة الاستخدام مدى الحياة في المعلمات العامة لـ const (https://github.com/rust-lang/rust/pull/74051)
  • contrun : تم إصلاح ICE (https://github.com/rust-lang/rust/pull/69859)
  • @ oli-obk: إعادة البناء (https://github.com/rust-lang/rust/pull/69981)
  • @ Centril : تشخيصات محسّنة (https://github.com/rust-lang/rust/pull/70261)
  • DutchGhost : تمت إضافة اختبار (https://github.com/rust-lang/rust/pull/70539)
  • varkor :

    • طباعة جميلة محسّنة (https://github.com/rust-lang/rust/pull/67909 ، https://github.com/rust-lang/rust/pull/68111)

    • تم إصلاح الأخطاء المتنوعة (https://github.com/rust-lang/rust/pull/67906 ، https://github.com/rust-lang/rust/pull/68388 ، https://github.com/rust- لانج / صدأ / سحب / 68434)

    • تشخيصات محسنة (https://github.com/rust-lang/rust/pull/70845)

    • الاختبارات المضافة (https://github.com/rust-lang/rust/pull/68312 ، https://github.com/rust-lang/rust/pull/70939)


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

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