Rust: مشكلة في تتبع "وحدات الماكرو 1.1" (RFC # 1681)

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

مشكلة تتبع الصدأ لانج / rfcs # 1681.

ccalexcrichton

الاستقرار TODO

اختبارات عباد الشمس:

ميزات:

  • اسم الصندوق ، حاليًا هو proc_macro
  • نوع الصندوق ، حاليًا proc-macro
  • السمة #[proc_macro_derive(Foo)]
  • تحميل صناديق proc-macro مع -L و #[macro_use] لتحميلها
  • التظليل خطأ
  • لا النظافة
  • تمرير دفق رمزي للبنية بأكملها واستلامها مرة أخرى
  • سمة بيان البضائع ، حاليًا proc-macro = true

الأخطاء المعروفة:

  • [] - قد يكون لمشتق الذعر النطاق الخطأ - # 36935
  • [] - تدفقات رمزية بـ mod foo تفشل - # 36691
  • [] - لا يتم نشر المستندات مقابل proc_macro - # 38749
  • [x] - السمات المخصصة لأوضاع متعددة صعبة - https://github.com/rust-lang/rust/issues/35900#issuecomment -252499766
  • [x] - فشل اختبار البضائع لـ proc macro libs - # 37480
  • [x] - الطلب لا يزال مهمًا - https://github.com/rust-lang/rust/issues/35900#issuecomment -252430957 (fxed بواسطة https://github.com/rust-lang/rust/pull/37067)
  • [x] - لا يمكن توثيق صناديق الماكرو rustc - https://github.com/rust-lang/rust/issues/36820 (ثابت في # 36847)
  • [x] - إعادة بناء البضائع كثيرًا - https://github.com/rust-lang/rust/issues/36625 (تم الإصلاح في https://github.com/rust-lang/rust/pull/36776)
  • [x] - تجعل السمات التي ينشئها المترجم حياة المؤلفين المشتقة المخصصة صعبة - https://github.com/rust-lang/rust/issues/35900#issuecomment -245978831

  • [x] - أنشئ صندوقًا rustc_macro

    • [x] - احصل على رابط librustc_macro إلى libsyntax . تعتمد على librustc_macro في librustc_driver
    • [x] - وضع علامة على rustc_macro أنها غير مستقرة مع العنوان القياسي .
    • [x] - ضع علامة فقط على rustc_macro بـ #![crate_type = "rlib"] ، لا تُنتج dylib.
    • [x] - تنفيذ واجهة برمجة التطبيقات لـ rustc_macro باستخدام libsyntax 's TokenStream داخليًا
    • [x] - ضع علامة على rustc_macro مع عنصر TokenStream lang حتى يعرف المترجم عنه.
  • [x] - أضف سمة rustc_macro_derive

    • [x] - تحقق من أنه بالشكل الدقيق foo(bar) ، ولا توجد وسائط / تنسيقات أخرى

    • [x] - تحقق من أنه ينطبق فقط على الوظائف

    • [x] - تحقق من أنه ينطبق فقط على الوظائف الموجودة في الوحدة النمطية الجذر

    • [x] - تحقق من التوقيع باستخدام عنصر lang TokenStream المضاف أعلاه

    • [x] - ترميز جميع رموز الوظائف بـ rustc_macro_derive في البيانات الوصفية جنبًا إلى جنب مع وضع الاشتقاق التي تستخدم من أجلها.

  • [x] - أضف نوع الصندوق rustc-macro للصناديق الأخرى

    • [x] - قم بتوصيله لإنتاج dylib

    • [x] - تأكد من أن dylib يحصل على البيانات الوصفية

    • [x] - تأكد من عدم إمكانية ربط الصناديق rustc-macro على أنها dylibs

    • [x] - تأكد من عدم وجود عناصر _ يمكن الوصول إليها_ بخلاف تلك التي تم وضع علامة عليها بـ #[rustc_macro_derive]

    • [x] - أضف cfg(rustc_macro) كتوجيه غير مستقر cfg ، اضبطه لنوع الصندوق rustc-macro

    • [x] - تأكد من أن الصناديق rustc-macro ترتبط ديناميكيًا بـ libsytnax

  • [س] - املأ #[macro_use] دعم rustc-macro الصناديق

    • [x] - قم بتوسيع أداة تحميل المكتبة للعثور على صناديق rustc-macro بشكل منفصل عن صناديق dylib / rlib التي يتم تعقبها اليوم عند وضع الصناديق

    • [x] - تحليل البيانات الوصفية لصناديق rustc-macro للتعرف على أزواج وضع الرمز / الاشتقاق

    • [x] - dlopen dylib

    • [x] - إنشاء خطأ إذا كان أي وضع اشتقاق سيظل موجودًا في أي وضع آخر.

  • [x] - إضافة تكامل البضائع

    • [x] - التعرف على rustc-macro مشابهًا لـ plugin = true

    • [x] - مرر --crate-type=rustc-macro عند الاعتماد عليها

    • [x] - استخدم نفس منطق المضيف / الهدف لصناديق الماكرو rustc كما هو موجود في صناديق المكونات الإضافية (على سبيل المثال ، قم دائمًا بتجميع صناديق rustc-macro للمضيفين)

  • [x] - الاختبارات

    • [x] - اختبار دخان يحمل سمة ماكرو صدأ ، دمية #[derive] سمة

    • [x] - تعارض الأسماء خطأ

    • [x] - يعد التحويل البرمجي للعمارة الخاطئة خطأ

    • [x] - لا يمكن إرسال نوع صندوق rustc-macro وأي شيء آخر (مثل rustc-macro + dylib) يعد خطأ

    • [x] - معلومات الامتداد ليست رهيبة

    • [x] - إزالة السمات من هيكل وكذلك الحقول

    • [x] - إضافة إشارات بجانب الهيكل

    • [x] - يبحث التجميع المتقاطع عن نوع صندوق الماكرو الصدأ المضيف

    • [x] - لا تقم بتحميل dylibs الفانيليا كأنواع صناديق الصدأ الماكرو

    • [x] - لا يمكن أن يكون هناك صادرات عامة تتجاوز وظائف الاشتقاق الكلي في صندوق rustc-macro

    • [x] - يجب أن تحتوي وحدات الماكرو المشتقة على توقيع مطلوب

    • [x] - تحميل صندوقين ماكرو في تجميع واحد

B-RFC-implemented B-unstable T-lang final-comment-period

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

حسنًا ، سأبحث في هذا اليوم وأرى إلى أي مدى وصلت.

ال 268 كومينتر

لقد قمت بتحديث وصف المشكلة بقائمة تحقق لما يجب القيام به. من المحتمل ألا يكون ذلك شاملاً ، لكن نأمل أن يقودنا إلى 90٪ من الطريق

حسنًا ، سأبحث في هذا اليوم وأرى إلى أي مدى وصلت.

سم مكعب https://github.com/rust-lang/rust/pull/35957 ، أحد التطبيقات

من # 35957: يجب أن نضع اسم صندوق librustc_macro على الدراجة. على وجه الخصوص ، يُقصد بهذا أن يكون صندوقًا طويل العمر يحتوي على أساسيات لجميع مؤلفي الماكرو فيه ، لذا فإن الحد من rustc_macro (والذي في رأيي على الأقل) هو مجرد فكرة 1.1 تبدو سيئة. كنت أرغب سابقًا في libmacro لهذا ، ولكن نظرًا لأن macro كلمة محجوزة (وقد نريدها ككلمة رئيسية في المستقبل) فهذا مستحيل. cgswords وأنا استخدم libproc_macro ، وأعتقد أن هذا ليس اسمًا سيئًا ، على الرغم من أنني لست سعيدًا به بنسبة 100٪.

nrc : حسنًا ، أفكاري الفورية حول التسمية:

  • extern crate macros; - قصير ولطيف ، ولكن يمكن قراءته على أنه يحتوي على وحدات ماكرو ، بدلاً من رمز الدعم لكتابتها
  • extern crate macro_runtime; - بالضبط ما هو مكتوب على العلبة
  • extern crate metarust; - اكتب Rust ، حول Rust ، للعمل على Rust
  • extern crate bikeshed; - مع وحدات الماكرو الإجرائية ، يمكنك الحصول على لون الصدأ الذي تريده!
  • extern crate macrame; - يبدو مثل "macro make [r]"؛ ربما من الأفضل تركه لواجهة برمجة تطبيقات "لطيفة" في المستقبل على المكتبة الأولية.

nrc يبدو أن أحد الجوانب المهمة في هذا السؤال هو تسمية أنماط الماكرو المختلفة لدينا بشكل عام - على وجه الخصوص ، إذا استخدمنا libproc_macro ، فإننا نلتزم بشدة بـ "الماكرو الإجرائي" المصطلح. ليس لدي رأي قوي هنا ، لكنني لست متأكدًا مما إذا كنا قد استكشفنا مساحة المصطلحات بشكل مفتوح.

لتوضيح الأمر ، هل تعتقد أن macro_rules سيكون ببساطة "وحدات ماكرو" ، أي الشيء الافتراضي الذي نعنيه بوحدات الماكرو ، بينما يتعين عليك تأهيل "وحدات الماكرو الإجرائية"؟ تبدو هذه خطة معقولة جدًا بالنسبة لي. وفي هذا العالم ، سأجادل بأن libproc_macro أفضل من libmacros .

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

لكن ، نعم ، أرغب بشدة في الوقوف وراء المصطلحات "الكلية الإجرائية".

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

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

مصطلح Perl لأقرب معادل لـ "وحدات الماكرو الإجرائية" هو "عوامل تصفية المصدر" ، والتي (خاصة مع التحول من AST إلى الرموز المميزة) وصف مناسب جدًا.

ربما تعمل "محولات النحو" أو "وحدات الماكرو البرمجية" بشكل جيد مثل الأسماء؟ ليس لدي مشكلة مع وحدات الماكرو الإجرائية.

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

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

أنا بخير مع libproc_macro أو libmacros . أنا أفضل نوعًا ما هذا الأخير لمجرد أنني لا أحب الحصول على أسماء الصناديق _ عندما يمكن تجنبها بسهولة. =)

سؤال واحد: هل نتوقع يومًا ما أن يكون لدينا "إجراءات دعم" يمكن استخدامها من وحدات ماكرو غير إجرائية؟ أنا لا أعرف أي خطط من هذا القبيل، ولكن إذا فعلنا، وأردنا لهم في نفس قفص، ثم libmacros سيكون اسما أفضل. =)

(أفكر قليلاً في ، على سبيل المثال ، تعليق dherman من RFC التوسعي

nikomatsakis : هناك سؤال مرتبط ولكن مختلف تمامًا وهو حالة الاستخدام التي أثارتها في https://github.com/rust-lang/rfcs/pull/1561#discussion_r60459479 - هل نريد أن تكون وظائف تنفيذ وحدات الماكرو الإجرائية قادرة على الاتصال وظائف تنفيذ وحدات الماكرو الإجرائية الأخرى؟

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

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

لديّ مندوب علاقات عامة خاص بالشحن https://github.com/rust-lang/cargo/pull/3064 والذي يجب أن يضع علامة في جميع خانات "تكامل البضائع" في قائمة التحقق.

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

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

نظرًا لأن هذا يظهر أن الصندوق نفسه يمكن أن يكون جزءًا عاديًا لصندوق آخر من وحدات الماكرو الإجرائية ، أو قسمًا ماكروًا لصندوق آخر.

هل يعمل Serde؟

نعم https://github.com/serde-rs/serde/releases/tag/v0.8.6

(باستثناء سمات الحاوية في بعض الحالات # 36211)

رائع ، شكرًا على التحديثات dtolnay!

هل توجد مستندات على وحدات الماكرو هذه؟ أفترض أن المثال الوحيد لاستخدامهم هو في serde ، هل أنا على حق؟

حسنًا ، هبطت بضائع الشحن. هذا جيد ، ولكن سيكون من الجيد إعادة زيارة https://github.com/rust-lang/rust/issues/35900#issuecomment -243976887 في وقت ما قبل الاستقرار. [لما تستحقه ، قصدت طرح هذا في RFC الأصلي لكن نسيت.]

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

nrc ، عندما تشير إلى "المكونات الإضافية الفعلية" ، هل تقوم بتضمين أشياء مثل metacollect و clippy ، أو أشياء مثل rustw ، و rustfmt ، لغة Rust ، أو فئة أخرى من البرامج؟

لما يستحق ، أنا أكره بشكل معتدل اسم "حسب المثال" (نظرًا لأن أنماط $foo ليست "أمثلة" في ذهني). يبدو التصريح مقابل الأمر أفضل بالنسبة لي.

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


نص الاستنساخ

(في صندوق اسمه demo_plugin )

#![feature(rustc_macro, rustc_macro_lib)]

extern crate rustc_macro;

use rustc_macro::TokenStream;

#[rustc_macro_derive(Foo)]
pub fn derive_foo(input: TokenStream) -> TokenStream {
    input
}

(في صندوق آخر)

#![feature(rustc_macro)]

#[macro_use] extern crate demo_plugin;

#[derive(PartialEq, Eq, Foo)]
struct Bar {
    a: i32,
    b: i32,
}

تؤدي إزالة #[derive(Eq)] إلى عمل كل شيء بشكل جيد.

sgrif آه نعم شكرا بالفعل

هناك بعض الأشياء التي تحدث هنا:

  • مع #[derive(PartialEq, Eq)] ، يضيف المترجم #[structural_match] بصمت لأنه يفهم بشكل ثابت أن الاشتقاق PartialEq يفي بالفعل بهذا العقد.
  • أعتقد أن سمة مماثلة تنشأ عند إضافة #[derive(Copy, Clone)] مع إضافة #[rustc_copy_clone_marker] .
  • يعمل هذا حاليًا لأن مدى هذه السمات يقول "يسمح بعدم الاستقرار الداخلي". ومع ذلك ، نفقد معلومات النطاق عند التحليل وإعادة التحليل.

لذلك ، بعض الحلول التي يمكننا القيام بها:

  • قل تقليديًا أن المشتق المخصص يأتي أولاً ، على سبيل المثال #[derive(Foo, Eq, PartialEq)]
  • الاعتماد على اشتقاق العرف لحذف هذه السمات
  • لا تصدر سمات مخصصة إذا اكتشفنا اشتقاقًا مخصصًا
  • استخدم آلية مختلفة تمامًا في المترجم لتوصيل ما تقوله هذه السمات ، ولكن ليس من خلال AST نفسها.

أؤيد إما عدم إصدار هذه السمات أو استخدام آلية مختلفة. هذا أمر صعب حقًا ، لأن #[derive(Copy, Foo, Clone)] يحتاج أيضًا إلى العمل (حيث يعمل الكود المخصص في المنتصف والذي يمكن أن يغير التعريفات).

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

إخلاء المسؤولية: لدي فقط وجهة نظر خارجية للمترجم - لذلك هناك الكثير الذي لا أعرفه. ^ ^

ولكن مما أفهمه ، فإن النهج الحالي للاشتقاق المخصص لوحدات الماكرو 1.1 يشبه إلى حد كبير الحل المؤقت. قد يتم ترجمة الحل المؤقت إلى "فترة طويلة". ولكن على المدى الطويل (= وحدات الماكرو 2.0) لن نقوم بإجراء تحليل السلسلة ذهابًا وإيابًا بعد الآن ، مما يؤدي حاليًا إلى فقدان معلومات الامتداد. أتساءل عما إذا كانت هذه السمات المخفية في AST كانت شيئًا سيئًا في عالم وحدات الماكرو 2.0. ربما يمكن لشخص لديه معرفة داخلية أكثر عن المترجم أن يخبرنا بذلك. إذا كانت هذه السمات المخفية منطقية حقًا في هذا العالم المستقبلي ، فسأجادل في البحث عن الحل عن طريق وضع المشتقات المخصصة في المقدمة. كل شيء بالفعل حل بديل على أي حال ، أليس كذلك؟

@ colin-kiegel أعتقد أنك على صواب بمعنى أن ما نقوم به الآن هو _لا_ دليل على المستقبل. لنفترض أن لديك ، على سبيل المثال:

#[derive(Eq, Foo, PartialEq)]

نضيف اليوم تنفيذ Eq ، ثم ننفذ الرمز المخصص لـ Foo ، ثم نضيف تنفيذ PartialEq . يمكن تغيير البنية بين Eq و PartialEq ، لذلك قد لا يكون #[structural_match] المضاف بواسطة Eq صحيحًا بعد تشغيل Foo .

بهذا المعنى ، أوافق على أنهم ليسوا بالضرورة دليلًا على المستقبل في أي حال!

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

نعم ، ستظل القدرة موجودة دائمًا على ما أعتقد (متأصلة في واجهة TokenStream -> TokenStream) على الرغم من أنني أشك في أن أي تطبيق معقول لـ #[derive] سيحتفظ بهيكل الهيكل الأصلي.

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

mystor نعم ، المشكلة في هذا النهج هي سمات غير معترف بها ، ولهذا السبب لدينا

إذا كان بإمكان المشتق المخصص v2.0 وضع علامة على السمات المخصصة كـ _ used_ ، فيمكن أن يقتصر على وصول _ read-only_ لبقية تدفق رمز العناصر. بهذه الطريقة يمكن ضمان توافق أفضل للمشتقات المخصصة IMO. إذا احتاج ماكرو v2.0 إلى تغيير بنية العنصر ، فسيتعين عليه استخدام واجهة برمجة تطبيقات أخرى ، ولكن ليس الاشتقاق المخصص. بهذه الطريقة ستكون المشكلة مع #[structural_mach] وطلب المشتقات (المخصصة) موجودة فقط في وحدات الماكرو 1.1. هل هذا منطقي؟

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


سيناريو الاستنساخ

في صندوق يسمى demo_plugin

#![feature(rustc_macro, rustc_macro_lib)]

extern crate rustc_macro;

use rustc_macro::TokenStream;

#[rustc_macro_derive(Foo)]
pub fn derive_foo(input: TokenStream) -> TokenStream {
    input
}

#[rustc_macro_derive(Bar)]
pub fn derive_bar(input: TokenStream) -> TokenStream {
    panic!("lolnope");
}

في قفص آخر

#![feature(rustc_macro)]

#[macro_use] extern crate demo_plugin;

#[derive(Foo, Bar)]
struct Baz {
    a: i32,
    b: i32,
}

سيظهر الخطأ Foo بالرغم من أن Bar أصيب بالذعر.

شكرا لتقريرsgrif! لقد قمت بتحديث وصف هذه المشكلة وآمل أن أتتبع جميع المشكلات المعلقة المتعلقة بوحدات الماكرو 1.1 هناك أيضًا.

حسنًا ، تفاعل الاشتقاق المخصص مع #[structural_eq] شيء لم أفكر فيه من قبل. بالأحرى يزعجني!

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

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

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

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

nrc حسنًا ، لا يزال من الممكن أن يكون tokenstream -> tokenstream ، حيث لا نكشف طريقة new التي تبدأ من الصفر ، أليس كذلك؟

أوافق على أنه يجب أن يكون من الممكن وجود سمات مخصصة في الحقول من أجل اشتقاق مخصص ليكون منطقيًا حقًا. لكنني أعتقد أنه قد يكون هناك العديد من الطرق للقيام بذلك باستخدام نمط "الإلحاق" - يجب بالطبع مناقشة هذا الأمر. أنا بالتأكيد أفضل أسلوب الإلحاق ، لأنني أفضل عالمًا لا تغير فيه وحدات الماكرو المشتقة العنصر وتكون قابلة للتكوين ، بالإضافة إلى أنها تحل مشكلة #[structural_eq] . هذا هو مجرد قدر مناسب من الحرية IMO.

إذا لم يعجب الناس هذا التمييز ، أود أن أسأل لماذا ، لأنه من الواضح أنه كان هناك سبب كافٍ للقيام بهذا التمييز من قبل ، أليس كذلك؟

(أعتقد أن ما اقترحته هو مجرد اختراق مؤقت ، ولا يعالج مشكلة قابلية التركيب على المدى الطويل.)

تحتوي مكتباتي المتنوعة حاليًا على وحدات ماكرو تشبه foo!(Bar, parameters...) ، والتي تنشئ بنية Bar من المعلمات.

خلال بعض المناقشات على IRC ، كانت لدينا فكرة لكتابة #[derive(Foo)] #[params] struct Bar; بدلاً من ذلك ، واستبدال foo! بـ #[derive(Foo)] الذي من شأنه أن يولد جسم الهيكل.

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

أتساءل عما إذا كان بإمكاننا إعادة صياغة #[structural_match] ليتم وضعه على التضمين الذي تم إنشاؤه بدلاً من ذلك.

(لا يحل المشكلة حقًا)

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

لذا ربما في الواقع لا أفكر بشكل مباشر في قضية #[structural_match] . بعد كل شيء ، ما الذي يمكن أن تفعله العادة؟

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

آسف لكتابة الكثير من التعليقات الصغيرة والتفكير بصوت عالٍ ، ولكن هناك مصدر قلق آخر. على الرغم من أن المشتق المخصص قد لا يكون قادرًا على "تزوير" التعليق التوضيحي #[structural_match] (لأنه سينتهي بدون "النطاق السحري") ، فإنه من المحتمل أن ينتهي بإفساد مدى أي تعليق توضيحي موجود ، ما لم يتم تطبيق المشتقات بالترتيب الصحيح ، وهو أمر مؤسف. بشكل أساسي مثال على عدم القابلية للتركيب الذي تحدث عنه @ colin-kiegel ، ولكن دون أي محاولة لتعديل البنية أثناء الطيران.

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

تحرير: حسنًا ، عند القراءة ، أرى أنني أعدت للتو ما ذكرتهsgrif بالفعل. آسف مرة أخرى. ؛)

إنه أيضًا إجمالي نوعًا ما ، لأنه يعني أننا نكشف تفاصيل التنفيذ غير المستقرة إلى كود ثابت. لن يعرف الرمز المستقر بشكل مثالي أبدًا أن التعليق التوضيحي #[structural_match] موجود.

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

@ كولين كيجل

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

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

إذا لم يعجب الناس هذا التمييز ، أود أن أسأل لماذا ، لأنه من الواضح أنه كان هناك سبب كافٍ للقيام بهذا التمييز من قبل ، أليس كذلك؟

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

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

أتفق مع jimmycuadra في أنه يبدو أن دعم السمات المخصصة بطريقة أو بأخرى هو مطلب صعب. nikomatsakis محق أيضًا على الرغم من أن المعاملة الحالية #[derive(PartialEq, Eq)] هي أقل من المستوى ولا ينبغي علينا تثبيتها. أخيرًا ، لدى mystor نقطة جيدة جدًا وهي أن أوضاع الاشتقاق المخصصة لا ينبغي أن تعرفها حتى عن هذه السمة السحرية. نحن ملزمون برغبة في إضافة المزيد في المستقبل ولا أريد أن تمنعنا وحدات الماكرو 1.1 من القيام بذلك.

أيضا مردداnrc الصورة المشاعر حول تصميم على المدى الطويل من ينحدر العرف، وأعتقد الكثير من هذا يتلخص في كيفية #[derive] يعمل فعلا. إذا وعندما ندعم السمات التعسفية ، أعتقد أن nrc لديه وجهة نظر جيدة حول امتلاك المعدِّلات فقط وعدم وجود زخارف ، لكن #[derive] خاص جدًا حيث لا يحدد المشتق المخصص سمة جديدة ولكن بدلاً من ذلك مجرد الانتقال إلى واحد موجود.

في الوقت الحالي ، يحتوي التطبيق على توسعة صارمة من اليسار إلى اليمين لأوضاع #[derive] . يتم توسيع جميع أوضاع الاشتقاق الداخلية في حلقة ، وكلما تم الضغط على وضع اشتقاق مخصص ، نقوم بإعادة التسلسل ، والتوسيع ، ثم العودة إلى المرحلة 1. وهذا بدوره يعني أن المترجم يمكنه تشغيل السمة #[derive] _multiple مرات لواحد تعريف نوع_. هذا يؤدي إلى حفنة من الشعر.

أحد الاقتراحات التي قد أطرحها هو تعديل أمر التوسيع #[derive] :

  • أولاً ، يتم توسيع كافة سمات الاشتقاق المخصصة من وحدات الماكرو 1.1 واحدة تلو الأخرى. بمعنى ، إذا كان لديك #[derive(Clone, Foo)] فسنشتق أولاً Foo حيث كان للبنية تعليق توضيحي #[derive(Clone)] . إذا استمر هذا #[derive] فسنشتق السمة المضمنة المخصصة Clone .
  • ثانيًا ، يتم توسيع كافة سمات الاشتقاق غير المعروفة من قبل المترجم إلى سمات #[derive_Bar] . هذا مجرد اختراق للتوافق مع الإصدارات السابقة يجب أن نزيله في مرحلة ما ، وهذه هي الطريقة التي يتم بها توسيع السمات.
  • أخيرًا ، يقوم المترجم بتوسيع جميع سمات #[derive] المعروفة والمضمنة

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

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


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

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

أود فقط أن أضيف أنني لا أحب فكرة أن المشتقات المخصصة يمكنها تغيير تخطيط الهيكل. أود أن أتمكن من استخدام هذا لشيء حساس للسلامة. كمثال ، ضع في اعتبارك تطبيق #[derive(Trace)] المستخدم بواسطة rust-gc .

#[derive(Trace)]
struct Foo {
    a: Gc<i32>,
}

التوسيع إلى:

struct Foo {
    a: Gc<i32>,
}

unsafe impl Trace { // NOTE: Strawman impl
    unsafe fn trace(&self) { Trace::trace(&self.a) }
}

ومع ذلك ، إذا سمحنا بتغيير الحقول في البنية ، فيمكننا تحديد مشتق مخصص Evil :

#[derive(Evil)]
struct Foo {
    a: Gc<i32>,
}

التوسيع إلى:

struct Foo {
    a: Gc<i32>,
    b: Gc<i32>,
}

والتي إذا قمنا بدمجها:

#[derive(Trace, Evil)]
struct Foo {
    a: Gc<i32>,
}

التوسيع إلى:

struct Foo {
    a: Gc<i32>,
    b: Gc<i32>,
}

unsafe impl Trace {
    unsafe fn trace(&self) { Trace::trace(&self.a) }
}

وهو تنفيذ غير سليم لـ Trace . عند استخدامه مع rust-gc ، فإن هذا يسمح لـ b أن يكون مرجعًا متدليًا ، وهو أمر غير آمن وغير سليم. هذا يعني أن Trace ليس شيئًا آمنًا لـ #[derive] بعد الآن على نوع ، وهو أمر مؤسف للغاية.

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

بعبارة أخرى ، لا أشعر أن "نقاء" وجود #[derive] لا يعدل الهيكل أبدًا يستحق التكلفة.

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

لدي شعور سيء بشأن السماح للاشتقاق بتغيير الهيكل. مثال mystor هو ما كان يدور في خلدي عندما كنت أتحدث عن قابلية التركيب .. على مستوى عالٍ (ربما لم يكن المصطلح الصحيح).

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

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

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

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

mystor يبدو هذا وثيق الصلة من الناحية النظرية ولكن تذكر أنك تحتاج بالفعل إلى توفير جميع مجالات الهيكل في Rust ، لذلك من غير المرجح أن تعمل بصمت بهذا الشكل ، مقارنة بـ C ++ ، على سبيل المثال.

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

أحد الاقتراحات التي قد أطرحها هو تعديل ترتيب التوسيع #[derive]

اعجبتني هذه الفكرة. ربما يكون الشيء الذي يجب ذكره من حيث التوثيق هو ببساطة أن ترتيب التوسيع "غير محدد". لقد قمنا بتوسيع PartialEq / Eq الماضي هذه الأيام ، ولكن لا يوجد سبب صارم للقيام بذلك.

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

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

تحرير: لقد غيرت رأيي ، ولا أرى أي سبب لعدم السماح

لذلك ، من وجهة نظري ، هذه هي الحجج للسماح لـ #[derive] المخصص بتغيير البنية:

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

في حين أن الوسيطات الخاصة بإضافة قيود إلى تطبيقات #[derive] المخصصة (مثل طلب اسم الهيكل والحقول / أسماء الحقول في البنية كما هي) هي:

  • يسمح للرمز الذي تم إنشاؤه بواسطة #[derive] مخصص بالاعتماد على هيكل النوع الذي يتم اشتقاقه من أجل السلامة (على سبيل المثال #[derive(Trace)] من rust-gc الذي _يجب_ رؤية نوع الدعم الفعلي ، أو أنه غير سليم ، من المحتمل أن يكون بطريقة خفية بعد الاستخدام الحر)
  • يقلل من احتمال التبعيات الضمنية في التوسعات الكلية ، حيث تقل المعلومات المنقولة بينها من خلال الهيكل

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

فكرة 1

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

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

فكرة 2

امنح كل ملحق اشتقاق مخصص نفس الإدخال TokenStream (النص الأصلي المكتوب في البرنامج). عندما يتم إعادة تحليل النتيجة ، سجل السمات التي لا تزال موجودة في بنية الإخراج. إذا كانت السمة موجودة في كل تدفق رمزي للإخراج ، فاشكو من السمة غير المستخدمة.

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

TL ؛ DR

باختصار ، أود أن أفهم ما هي الميزة الخاصة بالسماح بتحوير الهياكل ، ولماذا تفوق مخاوف السلامة الخاصة بجعل الأمان #[derive(Trace)] و #[derive(Serialize)] إلخ. ممكنًا. أنا متأكد من أنه إذا انتهينا من السير في مسار البنيات المتغيرة ، فسيكون هناك سبب وجيه ، لكنني سأكون حزينًا للغاية لتغيير اسم مشتق التتبع المخصص الخاص بي إلى #[derive(unsafe_Trace)] .

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

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

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

تعجبني فكرة nikomatsakis لإضفاء الطابع العشوائي على ترتيب التوسيع

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

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

من المحتمل أن يكون

sgrif PS: صحيح أن معظم مؤلفي الصدأ ربما يفهمون ما يحدث في التعليمات البرمجية الخاصة بهم ، وبالتالي قد لا يفاجأون بتعديلات البنية إذا اختاروا استخدام مثل هذا الماكرو عن قصد.

من المؤكد أن حالة الاستخدام العامة لتطبيق وحدات الماكرو على البنيات عبارة عن _ مزيج من تعديلات الهيكل + الزخارف. لكني أتوقع أن تكون النسبة العامة "الكثير من الزخارف" مع "تعديلات قليلة فقط". من الجيد أن يكون هناك فصل واضح هنا ، لأن ذلك يحسن قابلية القراءة والمرونة.

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

لذا ، بينما أجد هذا الجزء من حجة mystor مقنعًا:

يسمح للرمز الذي تم إنشاؤه بواسطة # [اشتقاق] مخصص بالاعتماد على بنية النوع الذي يتم اشتقاقه من أجل السلامة (على سبيل المثال # [اشتقاق (تتبع)] من الصدأ- gc الذي يجب أن يرى نوع الدعم الفعلي ، أو إنه غير سليم ، من المحتمل أن يكون بطريقة خفية بعد الاستخدام الحر)

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

#[mangle] // <-- custom decorator that does bad things to struct definition
#[derive(Trace)]
struct Foo {
    x: T, y: U
}

قد يكون أحد الأفكار هو أن الضمانة Trace يمكن كتابتها بطريقة تفشل _it_ في التجميع إذا تغير تعريف struct . فمثلا:

unsafe impl Trace for Foo {
    fn trace(&self) {
        let &Foo { ref x, ref y } = self;
        <T as Trace>::trace(x);
        <U as Trace>::trace(y);
    }
}

لاحظ أنه على الرغم من أن #[mangle] يمكن أيضًا أن يثبّت من جهازك إذا كان شيطانيًا حقًا. =) هناك الكثير مما يمكننا فعله هنا.

بصفتي مراقبًا لهذه المحادثات ، سأكون سعيدًا بالحصول على القاعدة الرسمية أو غير الرسمية التي تقول إن #[derive] مسموح له فقط بإضافة كتل impl وتقديم تعليق توضيحي للأخوة (يبدو #[mangle(Foo, Bar)] جيد بالنسبة لي 😸) مخصص لتغيير هيكل النوع. يمكن أن يكون لدى #[mangle] أمر تقييم محدد.

ربما يلزم وجود أمر تقييم محدد بين التعليقات التوضيحية إذا لم تكن موجودة بالفعل.

أعتقد أن آرائي قد خففت. يشيرnikomatsakis إلى نقطة جيدة مفادها أنه حتى لو تخلصنا من الهياكل المتغيرة داخل # [اشتقاق] فلن let Foo{ ... } ستعمل للتأكد من صحة التصميم في الحالات المعقولة. ربما نحتاج إلى توثيقه في مكان ما ولكن حتى لا يضطر الجميع إلى اكتشافه بشكل مستقل.

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

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

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

فيما يتعلق بالحالات التي تحتاج إلى تعديل الجزء الداخلي للعنصر الذي يتم تطبيق السمة عليه ، فقد صادفت للتو موضوع "ملاحظات ما قبل التنفيذ لـ Qt with Rust" في u.r-l.o ، وقمت بعمل هذا المنشور:

https://users.rust-lang.org/t/pre-implementation-feedback-for-qt-with-rust/7300/19

أحد الجوانب البارزة هنا ، أقترح تطبيق #[derive] (أو ما شابه) على _trait_ ، بدلاً من البنية - وسيكون العنصر المضاف بداخله طريقة سمة const .

على غرار قضايا الشحن التي أثرتها أعلاه ، لست متأكدًا منها

#[macro_use]
extern crate double;

استيراد وحدات ماكرو إجرائية من صندوق يسمى double . نظرًا لأننا نستخدم رمز وقت التشغيل (كما هو الحال في Ruest الحقيقي) في وقت الترجمة ، يجب أن يكون هناك بيان استيراد متزايد المرحلة مماثل لـ Racket (require (for-syntax ...)) . [مستند المضرب هو https://docs.racket-lang.org/reference/require.html#٪ 28form ._٪ 28٪ 28lib._racket٪ 2Fprivate٪ 2Fbase..rkt٪ 29._for-meta٪ 29٪ 29، للأسف لا أستطيع معرفة كيفية ربط القسم الصحيح.]

تشير مشاركة المدونة http://blog.ezyang.com/2016/07/what-template-haskell-gets-wrong-and-racket-gets-right/ إلى أخطاء التدريج التي حدثت في نموذج هاسكل وقد تكون ذات فائدة- - لا أريد أن أرتكب نفس الأخطاء في Rust.

@ Ericson2314 الفرق في Rust هو أن double قد تم تجميعه بالفعل _ لمرحلة معينة_.
أي أن الصندوق يقوم فقط بتصدير واجهة الماكرو / المُعدِّل ، كما لو تم تعريفها باستخدام ، على سبيل المثال macro_rules .
ستكون القدرة على إنشاء الصناديق التي تقوم بتصدير كل من وحدات الماكرو الإجرائية وعناصر الصدأ الأساسية (التي تشكل الماكرو الإجرائي) أمرًا مثيرًا للاهتمام ، ولكن حتى الآن لا يبدو أنه مقترح بأي صفة.

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

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

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

على جانب serde ، إليك قائمة مختصرة بالمشكلات المتبقية قبل أن نتمكن من التوقف عن دعم المكون الإضافي للمجمع الحالي والتوصية رسميًا بـ Macros 1.1 لجميع المستخدمين الليليين: https://github.com/serde-rs/serde/issues/545. الشيء الوحيد الذي نحتاجه من Rust هو إصلاح # 36211. كل شيء آخر نحرز تقدمًا سريعًا فيه.

لديّ علاقات عامة مفتوحة تنفذ rustc_macro دون استخدام syntex ، لذلك يمكننا التوقف عن القلق بشأن وقت التجميع https://github.com/serde-rs/serde/pull/548.

تحرير: لا يهم ، # 36211 أثرت فقط على تنفيذ syntex القديم

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

@ dtolnay مُعطى serde-rs / serde # 548 ، هل هناك أي حاصرات متبقية لـ serde؟

sgrif رائع ، شكرا! بمجرد القيام بذلك (أو قبل ذلك) ، هل يمكنك التعليق هنا باستخدام أي مانع متبقي واجهته؟

نعم سأفعل.

في الثلاثاء ، 27 سبتمبر 2016 ، 7:29 مساءً Alex Crichton [email protected]
كتب:

dtolnay https://github.com/dtolnay إعطاء serde-rs / serde # 548
https://github.com/serde-rs/serde/pull/548 ، هل هناك أي باقٍ
حاصرات ل serde؟

sgrif https://github.com/sgrif رائع ، شكرًا! بمجرد القيام بذلك
(أو قبل ذلك) هل يمكنك التعليق هنا باستخدام أي أدوات حظر متبقية لديك
واجهت؟

-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/rust-lang/rust/issues/35900#issuecomment -250028743 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/ABdWK7MnA1rpn-WGji8gwAT2JCIqB4LFks5quaa-gaJpZM4JqEAX
.

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

بالنظر إلى serde-rs / serde # 548 ، هل هناك أي حاصرات متبقية لـ serde؟

لا ، إذا قام @ oli-obk أو erickt بمراجعة تلك العلاقات العامة اليوم أو غدًا ،

@ dtolnay أنا روما وأود مساعدتك في اختبار serde_derive أيضًا ، إذا كنت بحاجة إلى مزيد من العيون.

في الواقع ، أنا أستخدم diesel_codegen أيضًا ، لذا فإن Ruma هي أرض اختبار جيدة لإصدار Macros 1.1 من هاتين المكتبتين.

لقد أصدرت Serde 0.8.10 معلنة أن serde_macros قد تم إهماله لصالح وحدات الماكرو 1.1.

دعنا نضيف مربع اختيار لـ "أعمال مستندات الشحن" - https://github.com/rust-lang/cargo/issues/3132.

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

لست متأكدًا مما إذا كانت هذه أخطاء serde_derive أم أخطاء rustc / rustdoc ، لكنني ألاحظ مشكلتين في المستندات التي تم إنشاؤها:

  • يظهر الحرف "///" في بداية سلاسل المستندات المُنشأة للأنواع التي تستخدم الاشتقاق المخصص.
  • لا يظهر Deserialize و Serialize في قسم "تطبيقات السمات" للأنواع التي تستخدم الاشتقاق المخصص.

يظهر الحرف "///" في بداية سلاسل المستندات المُنشأة للأنواع التي تستخدم الاشتقاق المخصص.

كان هذا خطأ syn . لقد أصدرت 0.8.2 مع إصلاح لذلك cargo update لاستلامه.

لا أعرف عن الثانية ، سأترك ذلك لـ alexcrichton.

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

  • لا يظهر Deserialize و Serialize في قسم "تطبيقات السمات" للأنواع التي تستخدم الاشتقاق المخصص.

هذا يبدو مريب جدا! يبدو أن هذا خطأ في rustdoc ، ولكن ربما ليس جديدًا. على سبيل المثال ، لا يُظهر rustdoc هذا مع تنفيذ Copy :

#[derive(Clone)]           
pub struct Point {         
    x: i32,                
    y: i32,                
}                          

const _FOO: () = {         
    impl Copy for Point {} 
    ()                     
};                         

يتم استخدام هذا النمط من قبل serde-derive لتوليد الضمانات. dtolnay هل كان لدى serde_macros نفس الشكل من الجيل أيضًا؟ هل سيكون من السهل الابتعاد عن الوقت الحالي لحل مشكلة التوثيق؟

jimmycuadra تريد فتح خطأ منفصل لتتبع قضية rustdoc حول ذلك؟

هل لدى dtolnay serde_macros نفس شكل الجيل أيضًا؟

نعم.

هل سيكون من السهل الابتعاد عن الوقت الحالي لحل مشكلة التوثيق؟

لا. على حد علمي ، هذا هو الحل الوحيد الذي يلبي كلا المعيقين:

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

راجع https://github.com/serde-rs/serde/issues/159 للحصول على التفاصيل.

dtolnay آه حسنًا ، للتوضيح ، @ jimmycuadra هذا ليس تراجعًا من قبل ، أليس كذلك؟

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

بالنسبة لأولئك الذين يتابعون ، فتحت # 36945 لإعادة تسمية rustc_macro إلى proc_macro تقريبًا في كل مكان والذي يبدو أنه إجماع على اسم هذا الصندوق.

يبدو أن تطبيقات السمات المفقودة في rustdoc (والتي يتم تعقبها الآن في مشكلة أخرى) ليست خاصة بوحدات الماكرو 1.1. آمن للتجاهل.

حاولت نقل مكتبة mockers من البرنامج المساعد للمترجم إلى وحدات الماكرو 1.1 وحصلت على "خطأ: لا يمكن تطبيق سمات الاشتقاق المخصصة إلا على عناصر الهيكل / التعداد". مع البرنامج المساعد للمترجم من الممكن (على الرغم من أنه غريب نوعا ما) استخدام "اشتقاق" في السمات. هل أنا محظوظ هنا؟

@ kriomant مثيرة للاهتمام! أعتقد أن هذا قد يكون في الواقع خطأ في الاشتقاق المخصص اليوم ، لأنني لست متأكدًا من أنه كان يُقصد به السماح لـ #[derive] للتطبيق على سمة ...

أعتقد أنه في الوقت الحالي ، من أجل التحفظ ، من المحتمل ألا نستقر على السمات حتى الآن ، ولكن ربما يمكننا إضافة ميزة غير مستقرة لها. خواطر @ رست لانج / لانج؟

alexcrichton ما الفرق بين السمات والبنى من جانب custom_derive؟

KalitaAlexey لا شيء ، إنه تقييد مصطنع لمطابقة التنفيذ الحقيقي derive

alexcrichton هل يمكننا تقديم دعم للسمات؟

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

أنا شخصياً لا أرغب في إضافة اشتقاق على سمة لأن ذلك يبدو أكثر بكثير على غرار منطقة السمة المخصصة بدلاً من اشتقاق نفسها. (على سبيل المثال يتعارض مع روح #[derive] كما تم إنشاؤه في الأصل)

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

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

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

👍 مني.

حسنًا ، الميزة غير المستقرة جيدة ، لكن هذا يعني أن مكتبتي لن تعمل بشكل ثابت (بدون إنشاء رمز). وبناء الجملة macro!(…) غير مشمول بـ "وحدات الماكرو 1.1" أيضًا ، هل أنا على صواب؟

أقوم بإعادة زيارة proc ماكرو RFC وكانت الخطة هناك أن صناديق الماكرو يجب أن تعلن عن نفسها #[cfg(macro)] . لا نطلب هذا لوحدات الماكرو 1.1 ، لكننا نطلب نوع صندوق خاص. الآليتين متعامدتان إلى حد ما - الأولى تصف مرحلة التجميع ، والثانية تصف نوع الصندوق. لكنها أيضًا متداخلة إلى حد ما - فهذا الأخير يعني الأولى. يتسع الأول أيضًا للإعلان عن وحدات ماكرو proc ووظائف غير ماكرو في نفس الصناديق ، في حين أن الأخير لا يفعل ذلك.

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

@ kriomant صحيح ، نعم

يتم تعريفnrc حاليًا على أنه cfg(rustc_macro) (على الرغم من أنه سيتغير قريبًا إلى proc_macro ). نحن لا نطلبه ، لا ، لكنني اعتقدت أنه سيكون ضروريًا لمفهوم ربط كل من الصندوق بوقت تجميع وكذلك في وقت التشغيل؟ أي أننا سنقوم بتجميع صندوق proc-macro مرتين: مرة باستخدام الصندوق من النوع proc-macro ومرة أخرى باستخدام الصندوق من النوع rlib ، ولن يرتبط الأخير بـ libsyntax أو أي شيء مثل ذلك.

في الوقت الحالي ، على الرغم من أنه يبدو من الجيد عدم _require_ ذلك ، على الرغم من أنني أعتقد أن هذا يعني في وقت لاحق أنه يتعين عليك الاشتراك في دعم وقت التشغيل؟ (تجميع الصندوق مرتين)

alexcrichton هل يمكن أن يعني ذلك #[proc_macro_derive] ؟ بنفس الطريقة التي يشير بها #[test] إلى #[cfg(test)] .
(لا يعني ذلك أنه يتعين علينا إضافته الآن ، فقط أن أسوأ حالة إذا أضفنا cfg هي تحذيرات عنصر غير مستخدمة.)

eddyb ماذا عن extern crate proc_macro; ؟ أشعر أن هؤلاء سوف ينكسرون أيضًا.

mystor إنه مجرد صندوق عادي به مجموعة من الأنواع والوسائل.

ألا يرتبط أيضًا بـ libsyntax الرغم من ذلك ، مما يعني أنه إذا استخدم الصندوق صندوق proc_macro وأراد أن يتقاطع مع التجميع ، فسيتعين عليه أيضًا عبور بناء الجملة؟

eddyb yes #[proc_macro_derive] يمكن تجاهلها تلقائيًا ، لكن المشكلة هي أننا _ أيضًا_ بحاجة إلى تجاهل كل شيء تصل إليه هذه الوظائف بشكل عابر (مثل extern crate proc_macro ). على الرغم من أنه "مجرد صندوق" ، إلا أن له آثارًا خطيرة على وقت التشغيل (الارتباط الديناميكي ، غير متاح للأهداف المجمعة ، إلخ).

لاحظ أن الاختبارات تحتوي على #[cfg(test)] ، لذلك يبدو من المعقول بالنسبة لي أننا ما زلنا نقدم #[cfg(proc_macro)] لنفس الغرض بشكل أساسي.

alexcrichton _Ideally_ ، لن يحتوي الصندوق على أكثر من ما تم تصديره ولن يتطلب ارتباطًا ديناميكيًا أو أي شيء من هذا القبيل ، فقط libstd . ومع ذلك ، يمكنني أن أرى أنه يسبب مشاكل في حالات #![no_std] .

يبدو أنه يتعين علينا القيام بالتجميع المزدوج من البداية إذا أردنا التقاط كل شيء: dis معين:

تحرير : انتظر ، ما الذي أفكر فيه؟ يتطلب نوع صندوق مخصص ، وينطبق التجميع المزدوج على الصناديق _ النظامية _ التي _أيضا _ تقوم بتصدير وحدات الماكرو / السمات / المشتقات الإجرائية / إلخ. لذلك لا صلة لها الآن.
ولكن يمكننا على الأقل تقديم #[cfg(proc_macro)] الذي يتم تعيينه دائمًا لنوع الصندوق الجديد.

🔔 تدخل هذه الميزة فترة التعليق النهائية بقصد الاستقرار في نهاية دورة الإصدار هذه! 🔔

الأساس المنطقي للنظر في الاستقرار الآن هو:

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

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

يبدو تجميع الصندوق مرتين أمرًا بسيطًا جدًا: لن يعمل تحديد النطاق بشكل صحيح. شيء مثل extern! crate needed_for_my_inline_proc_macros; هو حل أجمل بكثير.

aturon ماذا ، ألم يبدأ الناس في استخدام هذه الأيام فقط؟

@ Ericson2314 لقد مرت فترة أطول قليلاً من ذلك ، ولكن كما يوضح تعليق FCP ، فإن _الحد الأدنى_ من الوقت قبل الشحن إلى القناة الثابتة هو ثلاثة أشهر من الآن ، وهو ما نشعر به أكثر من كافٍ لهذه الواجهة الضيقة للغاية.

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

آه طيب. تذكرت الجزء 3 أشهر ، ولكن نسيت موقع FCP داخل تلك الأفواه الثلاثة --- خشية أن يكون 3 أشهر من 22 أغسطس. بغض النظر عن التوقيت ذلك الحين.

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

alexcrichton لا يزال rustc_copy_clone_marker و rustc_attrs يعضنا. راجع https://github.com/serde-rs/serde/issues/577.

#[derive(Copy, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct MyStruct {
    value: i64,
}

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

#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[derive(Copy, Clone)]
pub struct MyStruct {
    value: i64,
}

لقد انتهيت من نقل https://github.com/sfackler/rust-postgres-derive إلى وحدات الماكرو 1.1 كان الأمر غير مؤلم نسبيًا ، لكن التعامل مع السمات التي تقرأها مشتقات متعددة يمثل ألمًا كبيرًا. واجه Serde نفس الشيء ، لكنه يتطلب مجموعة من المنطق الغريب لتوسيع كلا المستمدين في نفس الوقت: https://github.com/sfackler/rust-postgres-derive/blob/master/postgres-derive-internals/ src / lib.rs # L26

لا ينبغي أن يمنع التثبيت ولكني أعتقد أنها مشكلة كبيرة نسبيًا من ناحية التأليف والتي ربما ينبغي علينا معالجتها قريبًا.

لقد أصدرت quote 0.3.0 مع دعم لتكرار نمط macro_rules! (شكرًا nrc على

pub fn enum_body(name: &str, variants: &[Variant]) -> Tokens {
    let num_variants = variants.len();
    let variant_names = variants.iter().map(|v| &v.name);

    quote! {
        if type_.name() != #name {
            return false;
        }

        match *type_.kind() {
            ::postgres::types::Kind::Enum(ref variants) => {
                if variants.len() != #num_variants {
                    return false;
                }

                variants.iter().all(|v| {
                    match &**v {
                        #(                           // \
                            #variant_names => true,  //  |----- new feature
                        )*                           // /
                        _ => false,
                    }
                })
            }
            _ => false,
        }
    }
}

لدي فضول ، لماذا # وليس $ ؟

تحرير : اعتقدت دائمًا أن صيغة الاقتباس ستكون ${...} ولكن ربما أكون مرتبطًا جدًا بالقوالب الحرفية ES6 حتى لو مرت عدة سنوات. \{...} يعمل أيضًا على الرغم من أنه سيكون مفيدًا في مكان آخر.
لا يبدو من الصعب تحديد الأقواس ولكن لا داعي للقلق.

لدي فضول ، لماذا # وليس $ ؟

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

macro_rules! demo {
    ($tt:tt) => {};
}

fn main() {
    demo!($v);
}

انتظر كل هذا يتم في macro_rules ؟! نسيت وحدات الماكرو 1.1 كانت مشتقة فقط للحظة. ومع ذلك ، فإن $x كونه رمزًا واحدًا هو عيب في التصميم IMO. MustafaHosny اللهم امين

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

alexcrichton لا يزال rustc_copy_clone_marker و rustc_attrs الآخرين يعضنا. انظر serde-rs / serde # 577.

يا عزيزي ، هذا يبدو سيئًا! سوف أقوم بتحديث القائمة في الأعلى. nrc أو jseyfried أفكار حول كيفية معالجة هذا الأمر؟ لست على دراية كبيرة بترتيب التوسيع لكل شيء ، ولكن ربما عندما يتم توسيع سمة واحدة #[derive] ، يمكن أن تحاول إفراغ كل الأشياء المستقبلية والقيام بذلك أولاً؟

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

التعامل مع السمات التي تقرأ من قبل مشتقات متعددة هو ألم كبير

لست متأكدًا من أنني اتبعت تمامًا المثال الذي ربطته ، هل يمكنك توضيح ذلك؟

alexcrichton خذ على سبيل المثال

#[derive(ToSql, FromSql)]
enum Foo {
    #[postgres(name = "bar")]
    Bar
}

يتم استخدام السمة #[postgres] لضبط كيفية إنشاء عمليات التنفيذ ToSql و FromSql . يجب تجريده قبل الإخراج النهائي لأنه بخلاف ذلك سمة غير معروفة ، ولكن يتم تشغيل تطبيقات ToSql و FromSql بشكل منفصل. إذا قمت بذلك بالطريقة الساذجة بمجرد إنشاء التنفيذ ثم تجريد السمات ، فستفتقد عملية الاشتقاق الثانية التخصيصات.

serde-derive و postgres-derive hack حول هذا في الوقت الحالي من خلال وجود تنفيذ لكلاهما يعني ضمناً إلى نفس الوظيفة التي تولد كليهما في وقت واحد. يتعين علينا إعادة إرفاق #[derive] للذي يتم استدعاؤه حاليًا منذ أن قام المترجم بتجريده ، ثم إرساله للتوسيع: https://github.com/sfackler/rust-postgres-derive/blob /master/postgres-derive/src/lib.rs#L18

sfackler I _think_ يمكنك أيضًا القيام بذلك عن طريق تجريد السمات الإضافية فقط عندما لا يكون هناك مشتق من نفس المنفذ المتبقي. قد يكون طريقك أفضل _shrug_.

sfackler آه حسنًا ، يبدو منطقيًا تمامًا. شكر!

أتساءل عما إذا كان هذا المنطق قد يكون هشًا. على سبيل المثال ، إذا كنت تقوم بتوسيع ToSql فكيف يتم اكتشاف التوسيع المستقبلي لـ FromSql ؟ يمكن أن يكون وراء #[cfg] مثل dtolnay المذكور أعلاه ربما؟ لذلك قد لا يكون من الممكن الكشف في جميع الحالات؟

alexcrichton نعم إنه هش ، ولهذا السبب يبدو الحل الحقيقي مهمًا.

ألا تتم معالجة #[cfg] و #[cfg_attr] قبل الاشتقاق؟

نظرًا لأن وحدات الماكرو 1.1 api تعمل على السلاسل ، يمكنني فقط تخيل ثلاثة حلول:

  1. اتركها كما هي وانتظر 2.0 وحدات الماكرو
  2. السماح بالسمات غير المستخدمة في الاشتقاق المخصص
  3. تمديد وحدات الماكرو 1.1 api بالسماح لمشتق مخصص بدفع أسماء السمات إلى قائمة بيضاء محددة للعنصر الحالي

كل خيار له إيجابيات / سلبيات خاصة به.
يخدع 1: حلول هشة في هذه الأثناء
يخدع 2: بعض السمات غير المستخدمة لن يتم الكشف عنها
يخدع 3: سطح أكثر API لحل مؤقت

لقد فكرت في تغليف السمات في #[used(...)] للاحتفاظ بها وإدراجها في القائمة البيضاء في نفس الوقت ، لكنها سخيفة جدًا ومستقرة للغاية.

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

عندما يتم توسيع سمة #[derive] ، يمكن أن تحاول جذب جميع السمات المستقبلية

اعجبتني هذه الفكرة. نظرًا لأن #[cfg] s و #[cfg_attr] s تتم معالجتها قبل #[derive] s ، فإن #[cfg] -guarded #[derive] s ليست مشكلة في هذا الأسلوب (أو لحل مشابه لـ

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

أحد الاحتمالات لمشكلة سمات التحكم هو إضافة عمليات الاسترجاعات بعد التوسيع ، والتي تشبه إلى حد ما لغة syntex: https://github.com/sfackler/rust-postgres-derive/blob/master/postgres-derive-codegen/src/lib. رس # L23 -L50

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

يعمل الديزل أيضًا يدويًا حول هذا. https://github.com/diesel-rs/diesel/blob/master/diesel_codegen/src/lib.rs#L101 -L112

dtolnay يجب إصلاح قلقك السابق بشأن سمات #[derive] المتعددة قريبًا بفضل jseyfried

لقد لعبت مع هذا باستخدام حزم syn و quote ، وكانت تجربة إيجابية حقًا. ستكون هذه ميزة رائعة عندما تستقر.

المشكلة المتعلقة بالسمات تقضم ضمني حاليًا ، حيث يتم تنفيذ منطق اشتقاق serde s.

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

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

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

error: custom derive attribute panicked
  --> src/simple.rs:69:1
   |
69 | struct C(u64);
   | ^^^^^^^^^^^^^^
   |
   = help: message: Failure parsing derived impl: LexError { _inner: () }

لقد قدمت حالة اختبار لـ LexError ، ويبدو أنه يحدث مع 13 أكتوبر ليلاً (لم يكن لدى rustup تحديثات) https://github.com/keeperofdakeys/proc_macro_derive_test.

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

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

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

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

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

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

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

  • من المؤكد أن فرض عقد الاشتقاق السلوكي يشبه حل الصدأ بالنسبة لي.
  • يمثل الحصول على serde و deisel للعمل مع هذا القيد الكثير من التحديات.

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

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

sgrif هل يمكنك توضيح كيفية استخدام deisel

withoutboats 90٪ منها أكثر أو أقل مما تتوقعه. نحن لا نلمس العناصر التي يوفرها المستخدم. نقوم بإزالة العناصر المشروحة لاختراق وحدات الماكرو في النظام. https://github.com/diesel-rs/diesel/blob/master/diesel/src/macros/macros_from_codegen.rs#L12 -L18. علاوة على ذلك ، فإن المرة الوحيدة التي نلمس فيها أي شيء في دفق رمز الإدخال هي إزالة التعليقات التوضيحية. https://github.com/diesel-rs/diesel/blob/master/diesel_codegen/src/lib.rs#L109 -L120

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

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

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

إذا كنا نتحدث عن شيء كان من المفترض أن يؤدي هذا الدور بشكل دائم ، فسأكون أكثر معارضة له

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

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

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

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

eddyb أنا أؤيد أن تكون الزخرفة قادرة على فعل أي شيء ، ولكن ليس لصالح أن تكون الزينة غير مقيدة (على المدى الطويل).

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

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

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

ألاحظ أيضًا أن ديزل لا تتبع نهج Serde في الحصول على جميع سماته المخصصة تحت اسم واحد (على سبيل المثال #[serde(rename = "name")] على عكس Diesel #[table_name = "name"] .) هل سيبسط التنفيذ إذا كان اسم سمة مخصصة واحدة فقط تم تسجيله بدلا من القائمة؟

أحد الاحتمالات لمشكلة سمات التحكم هو إضافة عمليات الاسترجاعات بعد التوسيع ، والتي تشبه إلى حد ما لغة syntex: https://github.com/sfackler/rust-postgres-derive/blob/master/postgres-derive-codegen/src/lib. رس # L23 -L50

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

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

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

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

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

ccalexcrichton ، dtolnay ، sgrif ، erickt - الأفكار؟

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

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

لوحظ أنه على الرغم من أن تعديل البيانات المستهدفة أمر مثير للدهشة ، إلا أنه ليس غير آمن.

إنه ليس غير آمن ، إلا إذا كنت تستمد صفة غير آمنة.

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

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

هل سيكون من الجيد تقسيم rfc السمات المخصصة إلى قسمين؟

  1. rfc لتوفير التدوين ومساحة الأسماء للسمات المخصصة بشكل عام (السماح بسمات no-op في الوضع الثابت).
  2. rfc لكيفية التعريف ، والدلالات حول تشغيل وحدات ماكرو السمات المخصصة.

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

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

هل هناك أي سبب لعدم احتواء هذا التنفيذ على وحدات ماكرو name! المعتادة؟ سوف يثبت Simple TokenStream in ، TokenStream الخارج لوحدات الماكرو المعتادة أنه مفيد للغاية في الآفات حيث تتجاوز أوقات الترجمة للقواعد النحوية المعقدة 30 ثانية.

dragostis لاقتباس ملخص rfc:

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

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

keeperofdakeys نعم ، فهمت ذلك. أنا لا أطلب تطبيق macros 2.0 ، فأنا أتساءل فقط عما إذا كان هناك أي عبء متضمن لإضافة سمة أخرى ، على سبيل المثال proc_macro هذا هو الحد الأدنى من التنفيذ الذي يعكس ببساطة تصميم الاشتقاق فقط لوحدات الماكرو المعتادة. سيشتق المثال في الآفات ببساطة محللًا لـ struct فقط لن يشتقها من struct نفسها ولكن من قواعد بسيطة محددة بين {} . آمل ألا أحفر مناقشات ميتة ، رغم ذلك!

nrc

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

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

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

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

sgrif

إذا كنا نتحدث عن شيء كان من المفترض أن يؤدي هذا الدور بشكل دائم ، فسأكون أكثر معارضة له

أردت أن أردد صدى withoutboats وتوضيح أن الهدف الحالي هو أن تظل وحدات الماكرو 1.1 سطح API كما هي حتى عندما نشحن وحدات الماكرو 2.0. هذا شيء يمكن أن نعيد النظر فيه ، على الرغم من ذلك - يمكننا التفكير فيه مثل قواعد الماكرو اليوم ، بقصد الإهمال بمجرد أن يصبح النظام النهائي في مكانه.

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

بهذا المعنى ، لست متأكدًا بنسبة 100٪ من أفضل طريقة للمضي قدمًا بشأن تلك السمات. سيكون من العار تثبيت وحدات الماكرو 1.1 ولكن لا يزال هناك عدد كبير من المستخدمين ليلاً (حتى لو كان "مستقرًا فعليًا" ليلا) لأن هذا إلى حد ما يهزم الغرض من التثبيت السريع لوحدات الماكرو 1.1 في المقام الأول. بعبارة أخرى ، إذا لم نسحب غالبية مستخدمي وحدات الماكرو 1.1 _ فعليًا_ إلى Rust المستقر ، فإن تثبيت وحدات الماكرو 1.1 أعتقد أنه يمكن الانتظار.

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

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

أميل إلى التبديل من تسلسل rustc إلى serde _ لأن إنشاء رمز serde يدعم سمات التحكم.

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

Dittojimmycuadra و sfackler ، السمات أكثر تكاملاً مع Serde من تعليق nrc يجعلها تبدو سليمة. سيتم تقديم جميع حالات الاستخدام بدون سمات تقريبًا أيضًا من خلال تسلسل rustc. إذا أردنا إبعاد الناس ليلًا ، فيمكننا القيام بذلك عن طريق إهمال Serde لصالح سلسلة rustc.

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

#[serde(skip_serializing)]

.. بدلا من:

/// <!-- serde(skip_serializing) -->

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

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

ما رأيك في تعليقي هنا في هذا الصدد؟ لقد وجدت هذا النمط مرضي.

أريد أن أوضح شيئًا واحدًا:

هل إزالة السمات المخصصة هو الشيء الرئيسي الذي ينبثق عنه الأشخاص باستخدام العرف؟

أعلم أن هناك بعض الاختراقات للقيام بتوسيع foo! في سياق أحد الأنواع (على سبيل المثال ، ذكر tomaka ذكرت واحدة أيضًا) - ما مدى أهمية حالات الاستخدام ؟

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

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

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

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

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

تحرير: لكن إضافة eddyb البيضاء تبدو واعدة أيضًا.

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

ستكون وحدات الماكرو الإجرائية التعسفية التي كنت أسيء استخدام نظام وحدات الماكرو 1.1 من أجلها في rust-cpp ممكنة تمامًا مع نهج بديل يوفر ببساطة القدرة على إضافة سمات ضمنية وتجاهل.

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

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

قد يكون السماح للمشتقات المخصصة بأخذ الحجج ، كما اقترح

#[derive(Debug, Clone, Serialize(field("bar", rename = "baz")))]
pub struct Foo {
  pub bar: String,
}

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

يتطلب كل من Serde وصندوقي سمات الحقل / البديل. محاولة محاكاة هذا مع اشتقاق الحجج لا معنى له ، نحن بحاجة إلى سمات.

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

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

FWIW السبب الوحيد لتجريد هذه السمات هو إبقاء HIR أقل نحافة - بقدر ما يتعلق الأمر بكل شيء آخر ، فأنت تحتاج فقط إلى تمييزها على أنها مستخدمة.

هل إزالة السمات المخصصة هو الشيء الرئيسي الذي ينبثق عنه الأشخاص باستخدام العرف؟

أعلم أن هناك بعض الحيل التي يجب القيام بها! التوسع في سياق أحد الأنواع (على سبيل المثال ، ذكر tomaka قد ذكر واحدة أيضًا) - ما مدى أهمية حالات الاستخدام هذه؟

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

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

يبدو أن هناك تراجعًا في آخر ليلة. الحصول على الخطأ

Queryable هو وضع اشتقاق

عند تجميع الأمثلة لدينا.

#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub published: bool,
}

sgrif كان السبب في ذلك هو # 37198 ، والذي تم تغيير المشتقات المخصصة لاستخدام نفس مساحة الاسم مثل وحدات الماكرو الأخرى (بحيث يتم مشاركة وحدات ماكرو bang!() ، ووحدات الماكرو #[attribute] ، ووحدات الماكرو #[derive(custom)] نفس مساحة الاسم).

في هذا المثال ، يستورد #[macro_use] extern crate diesel; ماكرو بانغ اسمه Queryable و #[macro_use] extern crate diesel_codegen; يستورد ماكرو مشتق مخصص يسمى أيضًا Queryable ، والذي يستبدل بصمت الماكرو بانغ (جانبا - #[macro_use] الكتابة الصامتة ليست مثالية ، لكنها لن تكون مشكلة بمجرد أن نتمكن من استيراد وحدات الماكرو من الصناديق الخارجية بـ use بدلاً من #[macro_use] ، قريبًا!).

أعتقد أن الخطأ ناتج عن استدعاء ماكرو مذهل Queryable!(); في توسيع المشتق المخصص ، والذي يتم حله إلى المشتق المخصص من diesel_codegen بدلاً من الماكرو الضخم من diesel .

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

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

المشكلة الحقيقية هي أنه لا يمكنك استخدام use لاستيراد أو إعادة تسمية وحدات الماكرو بشكل انتقائي. لذلك ليس لدى مستخدم الصندوق القدرة على الالتفاف حول تعارضات اسم الماكرو. في الوقت نفسه ، لا أتوقع ببساطة استيراد صندوق ProcMacro ليتعارض مع أسماء الماكرو المحلية - اعتقدت أن وحدات الماكرو المشتقة بدأت بـ derive_ ؟

هناك تكلفة معقدة في وجود مساحات أسماء وأعتقد أنه كلما كان لدينا عدد أقل كان ذلك أفضل ، لذا يجب أن يكون السؤال هو لماذا نحتاج إلى مساحات أسماء مختلفة؟

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

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

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


هل تقول أن _جميع العناصر يجب أن تكون في نفس مساحة الاسم إذا لم تكن تغييرًا فاصلًا؟ تحاول توضيح عملية تفكيرك.

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

المشكلة الحقيقية هي أنه لا يمكنك استخدامها لاستيراد أو إعادة تسمية وحدات الماكرو بشكل انتقائي.

ستكون قادرًا على ذلك باستخدام وحدات الماكرو 2.0. النموذج هنا هو في الأساس اختراق مؤقت.

اعتقدت أن وحدات الماكرو المشتقة بدأت بـ derive_؟

كان هذا هو نظام الاشتقاق المخصص القديم ، ولا أعتقد أن وحدات الماكرو 1.1 تفعل ذلك.

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

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

هل ستقول إن جميع العناصر يجب أن تكون في نفس مساحة الاسم إذا لم تكن تغييرًا مفاجئًا؟ تحاول توضيح عملية تفكيرك.

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

لكن هذا ليس القرار الذي اتخذه Rust للعناصر غير الكلية

Counterpoint: الوحدات النمطية والحقول موجودة في مساحة اسم القيمة ، على الرغم من أن الأماكن التي يمكن استخدامها (أعتقد) مختلفة عن الأماكن التي يمكن استخدام القيم الأخرى.

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

المشكلة الحقيقية هي أنه لا يمكنك استخدام use لاستيراد أو إعادة تسمية وحدات الماكرو بشكل انتقائي

سنتمكن من الوصول إلى وحدات ماكرو use من extern crate s خلف بوابة ميزة قريبًا (~ أسبوع واحد) ، راجع https://github.com/rust-lang/rfcs/pull/1561 و # 35896. قد نقرر تثبيت وحدات الماكرو use ing من صناديق الاشتقاق المخصصة جنبًا إلى جنب مع المشتقات المخصصة نفسها.

اعتقدت أن وحدات الماكرو المشتقة بدأت بـ derive_

كان هذا صحيحًا بالنسبة للمشتقات التقليدية ذات الطراز القديم. باستخدام المشتقات المخصصة لوحدات الماكرو 1.1 ، يتوقع #[derive(Serialize)] (على سبيل المثال) Serialize للتحليل إلى ماكرو مشتق مخصص.

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

ما هو سبب استخدام مساحة اسم واحدة لجميع "أنواع" وحدات الماكرو الثلاثة؟

  • الأسبقية: تشترك وحدات الماكرو ووحدات ماكرو السمات في مساحة اسم لفترة طويلة ، لذلك حتى تلك التغييرات أعتقد أن المشتقات المخصصة يجب أن تشارك مساحة الاسم هذه أيضًا.
  • التوافق مع الإصدارات السابقة: إذا بدأنا بمساحة اسم ماكرو واحدة ، فيمكننا تقسيمها إلى الخلف بشكل متوافق. إذا بدأنا بمساحات أسماء ماكرو متعددة ، فنحن عالقون معهم إلى الأبد.
  • البساطة: إذا كان لكل ماكرو "نوع" مساحة الاسم الخاصة به ، فسيكون لدينا خمسة مساحات أسماء إجمالية. وبالتالي ، بعد https://github.com/rust-lang/rfcs/pull/1561 الأراضي ، يمكن لـ use foo::bar; استيراد _ خمسة عناصر منفصلة_ باسم bar (قيمة ، نوع ، ماكرو بانج ، وما إلى ذلك) ، ولن تكون هناك طريقة بسيطة ، على سبيل المثال ، لإعادة تصدير ماكرو بانج ولكن ليس ماكرو الاشتقاق المخصص أو لاستيراد ماكرو الاشتقاق المخصص على أنه baz .

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

هذا مقنع ، خاصة وأن 1.1 من المفترض أن يكون فجوة مؤقتة. : +1:

هل هذا كسر الكود لأي شخص لديه ماكرو macro_rules يسمى مثل PartialEq! ؟

لا ، لم يتم تعريف PartialEq في مساحة اسم الماكرو اليوم لأنه ليس مشتقًا مخصصًا.
يتحقق #[derive(Foo)] أولاً مما إذا كان Foo "مشتقًا داخليًا" ( PartialEq ، Copy ، إلخ) قبل البحث عن مشتق مخصص Foo في مساحة اسم الماكرو. يتم ترميز المكونات المضمنة في تعريف derive .

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

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

  • خلف الكواليس ، تنفذ وحدات ماكرو الاشتقاق المخصص سمة ، حاليًا MultiItemModifier . إنها الخطة التي ستستمر فيها وحدات الماكرو 2.0 في تنفيذ سمة ويتم استخدام هذه السمة لتوسيع الآلية. تقوم الوظيفة المشروحة وهي الماكرو بتنفيذ هذه السمة. على الرغم من أننا لا نستخدم مسجل البرنامج المساعد ، إلا أن هذا يعد في الأساس أمرًا مزعجًا.
  • يجب علينا فصل سمة CustomDerive خصيصًا للمشتق المخصص لوحدات الماكرو 1.1. في الحالة العامة ، لا يراها مؤلفو الماكرو أبدًا. لكن لديهم خيار تنفيذ السمة مباشرة ، بدلاً من استخدام سمة على وظيفة (أتوقع أننا سوف نعيد استخدام السمة في الضمنية ، ربما نحتاج إلى مناقشة آلية التسجيل هذه).
  • نضيف دالة declare_attributes إلى CustomDerive والتي تُرجع Vec<String> . يحتوي على ضمني افتراضي يعيد vec فارغ.
  • إذا طبق مؤلفو الماكرو هذه الطريقة ، فإن أي سمات مسماة تمامًا كواحدة من السلاسل التي تم إرجاعها تعتبر تنتمي إلى الماكرو. لا يتم أبدًا البحث عن أي سمة من هذا القبيل مثل ماكرو ولا تقوم بتشغيل ملف السمة المخصصة. تُترك السمات في الكود عن طريق التوسيع المشتق ، ولكن يتم تمييزها على أنها مستخدمة. أي سمة من هذا القبيل لم تتأثر بتوسيع اشتقاق ستظل تؤدي إلى تشغيل سمة السمة غير المستخدمة (ولكن ليس نص السمة المخصصة).
  • قد نقدم في المستقبل سمات محددة النطاق يمكن أن تستخدمها وحدات الماكرو بما في ذلك المشتقات المخصصة ، وستكون هذه _بالإضافة إلى_ declare_attributes ولن يتم إهمال هذه الآلية.
  • بديل: يتم فحص السلاسل التي تم إرجاعها بواسطة declare_attributes كبادئة مسار للسمات ، على سبيل المثال ، إذا أعاد vec!["foo::bar"] declare_attributes vec!["foo::bar"] ، ثم #[foo::bar::baz] و #[foo::bar::qux] .

أفكار؟ سم مكعبalexcrichtonjseyfrieddtolnaysgriferickt @ الصدأ لانغ / لانج

nrc هل تسمح هذه الآلية بتعطيل سمات _used_ مثل #[cfg(..)] - إما عن طريق الصدفة أو عن قصد؟ وهل يمكن تغيير ذلك؟

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

ومع ذلك ، فأنا متشكك إلى حد ما فيما إذا كانت الصفات والأشياء ستعمل ، لأنه أين توجد أمثلة السمة التي يتم إنشاؤها؟

nrc لماذا يجب أن يكون هذا أمرًا حتميًا ولا يمكن أن يكون مجرد قائمة في السمة تحدد وظيفة derivw الموسعة؟ على سبيل المثال ، #[proc_macro_derive(Serialize, uses_attrs(serde_foo, serde_bar))] أو ما شابه.

@ colin-kiegel أتخيل أنه لا يمكن تطبيقه إلا في نطاق تطبيق الاشتقاق ، وفي هذه الحالة من المحتمل أن يكون تعطيل السمات الأخرى سلوكًا متوقعًا ، على الرغم من أنني أعتقد أننا قد نطبق cfgs قبل التوسع الكلي (لقد تغير هذا ، لكن لا يمكنني تذكر ذلك قبل مقابل بعد).

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

ومع ذلك ، فأنا متشكك إلى حد ما فيما إذا كانت الصفات والأشياء ستعمل ، لأنه أين توجد أمثلة السمة التي يتم إنشاؤها؟

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

eddyb هذه فكرة جيدة وربما أسهل في

التعافي - لقد خرجت من البلاد ثم مرضت. أرغب في زيارة https://github.com/rust-lang/rust/pull/37198 ، حيث لا أعتقد أنه من المنطقي أن تشغل جميع أنواع وحدات الماكرو نفس مساحة الاسم. أتوقع على الأقل أن تكون وحدات الماكرو المشتقة المخصصة في مساحة الاسم هذه كـ derive_Foo ، أو ما شابه ذلك. هناك حالات استخدام لأنواع متعددة من وحدات الماكرو تستخدم نفس الاسم حتى في المكتبة القياسية (على سبيل المثال ، #[cfg] و cfg! )

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

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

sgrif @ colin-kiegel لقد وصفت الأساس المنطقي لمساحة اسم ماكرو واحدة في https://github.com/rust-lang/rust/issues/35900#issuecomment -256247659.

لا أعتقد أنه من المنطقي أن تشغل جميع أنواع وحدات الماكرو نفس مساحة الاسم

للتوضيح ، احتلت وحدات الماكرو الضخمة ووحدات ماكرو السمات دائمًا نفس مساحة الاسم ؛ # 37198 تم نقل مشتقات مخصصة إلى مساحة الاسم هذه.

هناك حالات استخدام لأنواع متعددة من وحدات الماكرو تستخدم نفس الاسم حتى في المكتبة القياسية (على سبيل المثال ، #[cfg] و cfg! )

بدلاً من ذلك ، يمكن عرض cfg كماكرو واحد يمكن استخدامه من خلال استدعاء بانج أو استدعاء سمة (بينما لا يمكن للمستخدمين اليوم تحديد ماكرو يمكن استدعاؤه من خلال ضجة أو سمة ، قد نقرر السماح به في وحدات الماكرو 2.0).

من منظور المستخدم النهائي ، قد يبدو الأمر كما لو كان هناك نوع من التبادلية

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

يبدو أنه لا يزال من الممكن تقديم مساحات أسماء مختلفة في المستقبل دون الانقطاع عن الكثير

أعتقد أن تقسيم مساحة اسم الماكرو متوافق تمامًا مع الإصدارات السابقة (صححني إذا كنت مخطئًا). هذا هو حافزي الرئيسي للاحتفاظ بمساحة اسم ماكرو واحدة اليوم - نريد أن تكون وحدات الماكرو 1.1 متوافقة مع المستقبل قدر الإمكان.

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

يبدو أن الكسر (https://github.com/diesel-rs/diesel/issues/485) ناتج عن الدعم ، على سبيل المثال Queryable! { struct S; } بالإضافة إلى #[derive(Queryable)] struct S; . بمجرد استقرار المشتقات المخصصة ، لن تكون هناك حاجة لدعم Queryable! { struct S; } لذلك لن تكون هذه مشكلة ، أليس كذلك؟

في غضون ذلك ، أعتقد أنه يمكننا تحديث diesel لذلك

  • لا يزال يتم دعم Queryable! بدون #[macro_use] extern crate diesel_codegen; و
  • #[derive(Queryable)] ، ولكن ليس Queryable! ، مدعوم بـ #[macro_use] extern crate diesel_codegen; .

لا تتردد في الاتصال بي على IRC للمناقشة - سأكون سعيدًا بكتابة العلاقات العامة.

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

ومع ذلك ، فأنا متشكك إلى حد ما فيما إذا كانت الصفات والأشياء ستعمل ، لأنه أين توجد أمثلة السمة التي يتم إنشاؤها؟

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

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

trait CustomDerive {
     fn foo(); // note: no self
     fn bar(); // again, no self
}

ستقوم بعد ذلك بتطبيقها على نوع وهمي مثل struct my_annotation_type; (مشاركة نفس اسم السمة ، أعتقد؟) ، وسنستخدم دقة السمات لاستخراج الوظائف ذات الصلة مثل <my_annotation as CustomDerive>::foo (ربما عند كتابة البيانات الوصفية ، على ما أعتقد). النقطة المهمة هي أننا لن نصنع (أو نحتاج) أبدًا مثيل my_annotation ، إنها مجرد آلية تجميع لتجميع مجموعة من الوظائف ذات الصلة معًا.

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

فيما يتعلق بمساحات الأسماء ، تقدم sgrif حالة جيدة مع الأمثلة #[cfg] و cfg! . يمكنني بالتأكيد تخيل شخص يريد الحصول على #[derive(SomeTrait)] ولديه أيضًا بعض الماكرو مثل SomeTrait! { ... } ... يقوم بشيء ما. =) لكن jseyfried يقدم أيضًا حالة جيدة مع التوافق مع الإصدارات السابقة - طالما أننا لا نواجه قيودًا بالفعل.

أنا أميل إلى تفضيل عدد أقل من مساحات الأسماء افتراضيًا ، ويرجع ذلك في الغالب إلى الألم الذي أعتقد أن تقسيم مساحة الاسم للقيمة / النوع يجلبه إلينا الآن. ومع ذلك ، أعتقد أن معظم نقاط الألم المعروفة لا تنطبق هنا:

  • تقسيم النوع / القيمة هو ألم في تحليل الاسم لأن use foo::bar قد يستورد أو لا يستورد وحدة باسم bar ، وبالتالي قد (أو قد لا) تكون ذات صلة بتحليل الاسم مثل bar::baz ؛
  • تقسيم النوع / القيمة هو نوع من الألم للأدوية على الثوابت ، على الرغم من أن هذا الألم يرجع أيضًا إلى الانقسام النحوي بين الأنواع والقيم.

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

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

keeperofdakeys ألن يكون هذا مكافئًا لمؤلفي الاشتقاق المخصص الذين يقررون تسمية derive_* ؟ بغض النظر ، أعتقد أن أسماء derive_* قبيحة جدًا للمستخدمين النهائيين.

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

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

يمكن لخوارزمية دقة الاستيراد معالجة العديد من مساحات الأسماء بشكل تعسفي ، ولكنها تؤدي قدرًا غير أساسي من العمل لكل مساحة اسم. على وجه الخصوص ، لكل استيراد I ولكل مساحة اسم غير مستخدمة S ، فإنه يثبت أن الدقة I تفشل في S (cf https: // github. com / rust-lang / rfcs / pull / 1560 # issuecomment-209119266). غالبًا ما يتطلب هذا الإثبات DFS للرسم البياني لاستيراد الكرة الأرضية (حيث تكون الرؤوس عبارة عن وحدات نمطية والحواف عبارة عن واردات كروية) للبحث عن الواردات غير المحددة ذات الصلة.

ومع ذلك ، قد لا يحدث هذا العمل الإضافي لكل مساحة اسم فرقًا في الممارسة ويمكن تجنبه إذا لزم الأمر (راجع https://github.com/rust-lang/rfcs/pull/1560#issuecomment-209119266) بتكلفة تقييد طفيف يتم تطبيقه فقط على مساحات أسماء الماكرو.

قمت بدمج مساحات الأسماء في # 37198 لإبقاء خياراتنا مفتوحة في الغالب ولأنني لم أعتقد أنها ستكون محدودة في الممارسة. إذا أراد الناس ذلك اليوم و @ rust-lang / lang على ما يرام مع وجود العديد من مساحات أسماء الماكرو إلى الأبد ، فليس لدي أي اعتراضات.

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

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

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

لقد شعرت بالفضول وبدأت في تنفيذ أساسي لهذه الفكرة (باستخدام سمة في وظيفة proc_macro للإشارة إلى أسماء السمات التي سيتم تمييزها على أنها مستخدمة في العنصر).

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

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

  • لا أحد يعتقد أنه يجب عليهم فعل ذلك - في الممارسة - بالطبع
  • إنه وضع آخر تم رفضه في البداية بروح YAGNI
  • الاشتقاق الذي يغير مجموعة أسماء الحقول وما إلى ذلك لا يؤلف جيدًا ، مما يجعل ترتيب التطبيق مرئيًا ؛
    يخفف من خطورة ذلك أمرين:
  • من ناحية أخرى ، إذا قلنا أن الاشتقاق المخصص يحتاج فقط إلى إرجاع الضمانات الجديدة

    • معلومات الامتداد أفضل

    • المشتقات المخصصة أسهل في الكتابة

  • _ولكن_ تستخدم العديد من الاشتقاقات المخصصة سمات مخصصة لتوجيه توسعها ، وستؤدي هذه إلى إنشاء تحذيرات / أخطاء

    • الأسلوب الحالي هو تجريدهم من AST

  • _أيضا: _ نريد نشر هذه الأشياء في العالم بأسرع وقت ممكن ، ولا نريد إجراء تجارب مطولة أو تغييرات جذرية

اقتراحات:

  • احتفظ بكل شيء كما هو ، وربما يتم إهماله لاحقًا

    • مناسب ، مؤسف إلى حد ما

  • قم بتوسيع #[proc_macro] بقائمة بيضاء من السمات ، واطلب من rustc اعتبارها "مستعملة" وتجاهلها

    • بسيط ، يغطي حالة الاستخدام الرئيسية

    • لكن شخصًا ما يحتاج إلى تنفيذه ( ربماkeeperofdakeys! )

السؤال 2: هل يجب أن تشترك المشتقات المخصصة في نفس مساحة الاسم مثل وحدات الماكرو الأخرى؟

حجة ل:

مجادلة ضد:

اقتراحات:

  • انقسام إلى مساحة اسم "اشتقاق مخصص"
  • حافظ على الوضع الراهن

اشياء اخرى؟

هل هناك أسئلة أخرى مفتوحة؟

الحل المحتمل لمشكلة الطفرات:

بدلاً من المشتقات المخصصة التي تحتوي على النوع TokenStream -> TokenStream ، سيكون لديهم كتابة بدلاً من ذلك
Item -> TokenStream ، حيث يكون Item نوعًا معتمًا يبدأ بطريقتين فقط:

  • item.tokens() ، الذي يُرجع TokenStream الذي سيتم تمريره اليوم ، و
  • item.use_attrs(name) ، والذي سيميز جميع السمات بالاسم المحدد على أنها مستخدمة.

سيتضمن TokenStream المرتجع فقط impl s المشتق.
يمكننا في النهاية إضافة إلى واجهة برمجة تطبيقات Item مع وظائف ملائمة (مثل التكرار فوق حقول / متغيرات العنصر) أو واجهة برمجة تطبيقات اشتقاق ذات مستوى أعلى مثل تلك الموجودة في syntax_ext::deriving::generic .

يسعدني تنفيذ السماح بالسمات المدرجة في القائمة البيضاء في #[proc_macro_derive] (أي الاقتراح الثاني للسؤال 1 في https://github.com/rust-lang/rust/issues/35900#issuecomment-258315395) أو اقتراحي Item -> TokenStream .

أعتقد أنه سيكون من الخطأ تثبيت المشتقات المخصصة التي يمكن أن تغير العنصر الأساسي. تتسبب معلومات الامتداد التي نضحي بها من خلال السماح بالطفرة بالفعل في حدوث مشكلات - على سبيل المثال ، يتعين علينا الاختيار بين إصلاح # 37563 وإصلاح # 36218.

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

لست متأكدًا ، هل هو مقصود / مرغوب فيه أن يجمع هذا الكود:

#![feature(proc_macro)]

#[proc_macro_derive(Whatever)]
struct Foo {}

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

هل ستحل وحدات الماكرو 2.0 محل واجهة برمجة التطبيقات هذه؟ إذا كان الأمر كذلك ، فإن القابلية للتوسعة ليست مصدر قلق حقيقي ، ولا تبدو واجهة برمجة التطبيقات Item -> TokenStream جذابة للغاية.

keeperofdakeys حسب RFC:

بشكل عام ، يجب اعتبار هذا خطوة تدريجية نحو "وحدات الماكرو 2.0" الرسمية.

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

https://github.com/rust-lang/rfcs/pull/1681#issuecomment -233449053 و https://github.com/rust-lang/rfcs/pull/1681#issuecomment -233708395 و https: // github. يبدو أن com / rust-lang / rfcs / pull / 1681 # issuecomment -239558657 يشير إلى أنه من المتوقع فقط إهمال "محدود" عند وصول وحدات الماكرو 2.0. على وجه الخصوص: "سيصبح نمط الأشجار المميزة ذات السلسلة النصية غير مفضل ، إذا لم يتم إهماله بالفعل".

eddyb

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

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

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

بالطبع ، سيأتي بعض هذا من (_أحداثًا_) بعض أشكال API AST القياسية أيضًا.

ملاحظة حول التوقيت: أريد حقًا أن أرى وحدات الماكرو 1.1 تستقر في الدورة التالية. تبدو الأشياء التي حظرنا عليها ، في النهاية ، بسيطة إلى حد ما.

بهذه الروح ، تناولت القضايا التي وصفتها:

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

nikomatsakis ملخص الخاص بك يبدو دقيقا، وذلك بفضل لكتابة عنه! أنا حزين لأننا لن نحصل على وحدات الماكرو 1.1 في Rust 1.14 ، لكنني أفهم أن هذه قضايا خلافية.

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

لا أتبع واجهة برمجة تطبيقات Item -> TokenStream ، فهل لا يزال تدفق الرمز المميز يشمل العنصر الأصلي أم الضمانات المضافة فقط؟ هل هذا يعني أنه يجب أن يستغرق &mut Item ؟

@ est31 تعليقك يبدو وكأنه خطأ ، هل يمكنك فتح قضية منفصلة لذلك؟

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

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

ظهرت المشكلة بسبب كسر الديزل ، والذي يحتوي حاليًا على وحدات ماكرو تسمى على سبيل المثال Queryable! والتي يمكنك لفها في هيكل لاشتقاق Queryable لذلك.

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

لقد قمت بإنشاء PR https://github.com/rust-lang/rust/pull/37614 للميزة المقترحة. يستخدم سمة منفصلة #[proc_macro_attributes(..)] ، ولم تعد بحاجة إلى إرجاع العنصر في TokenStream إرجاعه.

لقد قدمت # 37637 لمعرفة كيفية تعامل وحدات ماكرو proc مع $crate .

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

أقوم بإنشاء هياكل جديدة بناءً على البنية والسمات الحالية هنا وأنا أحب التصميم تمامًا لأنه يسمح لي بدمج الأشياء في هيكل واحد.

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

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

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

التغيير الرئيسي الآخر هو القدرة على توفير قائمة بأسماء السمات التي لا ينبغي أن تؤدي إلى أخطاء السمات المخصصة على العنصر.

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

أعتقد أنه من المؤسف أن تفقد القدرة على تعديل تدفق الإدخال. تتيح لنا القدرة على إزالة العنصر الذي يتم التعليق عليه الحصول على وحدات ماكرو مذهلة مع هذا النظام أيضًا. أنا أتفهم المخاوف ، لكن من العار أن تفقد هذه القدرة عليها.

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

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

@ TheNeikos لا أعتقد أننا

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

sgrif

أعتقد أنه من المؤسف أن تفقد القدرة على تعديل تدفق الإدخال. تتيح لنا القدرة على إزالة العنصر الذي يتم التعليق عليه الحصول على وحدات ماكرو مذهلة مع هذا النظام أيضًا. أنا أتفهم المخاوف ، لكن من العار أن تفقد هذه القدرة عليها.

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

تم دمج PR ، لذلك يجب أن تكون قادرًا على رؤية التغييرات التالية في الليلة التالية. يجب ألا تقوم وظيفة proc_macro_derive بعد الآن بإرجاع العنصر (سيؤدي القيام بذلك إلى ظهور خطأ حول نوع تم تعريفه مرتين) ، ويمكنك الآن تقديم قائمة بأسماء السمات إلى القائمة البيضاء مثل #[proc_macro_derive(Derive, attributes(Foo, Bar)] .

cc dtolnay ، sgrif ^

هذا سوف يسبب الكسر قريبا للأسف

نعم ، لقد قدمت https://github.com/serde-rs/serde/issues/614 للتتبع من جانبنا.

أعتقد أنني أصلحت الكسر في ديزل في https://github.com/diesel-rs/diesel/pull/493 ، وسأعرف بالتأكيد بمجرد أن يتم بناء الليل مرة أخرى.

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

لديّ ماكرو #[derive(newtype)] proc في صندوقي (الصغير ، غير المنشور) الذي يتوسع إلى مجموعة مختلفة من #[derive()] s الأخرى بناءً على البنية التي يعلق عليها. على سبيل المثال ، يتوسع #[derive(newtype)] struct Foo(u64) إلى #[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] struct Foo(u64); بينما يتوسع #[derive(newtype)] struct Foo(::semver::VersionReq) إلى #[derive(Clone, Debug, PartialEq)] struct Foo(::semver::VersionReq); . لذلك لا يتم تعديل أعضاء البنية بواسطة هذا الماكرو ، ولكن تتم إضافة مشتقات أخرى إليه (لا تعدل هذه البنية أيضًا).

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

اعتدت أن يكون لدي ماكرو macro_rules newtype! لهذا ولكني تحولت إلى ماكرو proc للأسباب التالية:

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

للأسف لا ، لم يعد بإمكانك القيام بذلك كما كنت تفعل.

فيما يتعلق بالتوافق المستقبلي لهذه الميزة كونه مستقرًا: نظرًا لأن الوظيفة الإضافية ليست مطلوبة لتكون "نقية" ، فهل سيكون تغييرًا مفاجئًا إذا تغير ترتيب الكائنات المعطاة للوظيفة المعالجة في المستقبل ، أو إذا كان rustc يطبق متعدد الخيوط تجميع؟

@ est31 إذا كان لدينا الوقت ، فعلينا أن نحاول التخلص من عزل IPC الذي تم ذكره.

أرى باستمرار محرك ICE في ديزل بعد أحدث التغييرات.

../src/librustc_metadata/decoder.rs:490: الإدخال: لم يتم العثور على المعرف: DefIndex (1) في الصندوق "diesel_codegen" برقم 28

sgrif سيكون هذا هو الإصدار رقم 37788 والذي سيتم إصلاحه بواسطة # 37793 (دعونا نأمل أن ينتهي به الأمر في كل ليلة غدًا ...).

@ est31 فات الأوان في هذه الساعة

https://github.com/rust-lang/rust/issues/37839 هي مشكلة في استخدام صندوق lib يستخدم نفسه صندوق proc_macro. AFAICT لا تتأثر أي من الاختبارات بهذا لأنها إما تقوم بتجميع وحدة ماكرو proc فقط أو وحدة ماكرو proc ووحدة حاوية تشير مباشرةً إلى ماكرو proc.

تحرير: ثابت الآن!

Arnavion تم --target ، كما ورد في # 37958. لقد قدمت الحد الأدنى من حالة الاختبار باستخدام --target والتي لا تزال فاصلة.

تضمينrfcbot fcp

الآن بعد أن تم تنفيذ ميزة السمة المدرجة في القائمة البيضاء ، أعتقد أنه يجب علينا تثبيت هذا! Serde و Diesel والمستخدمون الآخرون - الآن هو تغييرك للعنصر إذا كان التصميم الحالي لا يناسبك. =)

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

اقترح عضو الفريق nikomatsakis دمج هذا. الخطوة التالية هي المراجعة بواسطة باقي الفرق الموسومة:

  • [x]alexcrichton
  • [x]aturon
  • [x] @ brson
  • [x]eddyb
  • [x]japaric
  • [x] @ michaelwoerister
  • [x]nikomatsakis
  • [x]nrc
  • [x]pnkfelix
  • [x] vadimcn
  • [x] @ بدون قوارب
  • [x]wycats

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

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

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

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

مراجعة rfcbot

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

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

أعتقد أن المستخدمين سيستفيدون أيضًا ، إذا كان ذلك فقط لتقديم تقارير أخطاء أفضل ضد الماكرو.

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

# 37480 مغلق ، والذي يجب أن ينعكس في قائمة المراجعة.

ثابت

pnkfelix لقد

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

psstnikomatsakis ، لم أتمكن من إضافة التصنيف final-comment-period ، يرجى القيام بذلك.

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

هناك نوعان الآن:

  • # 36935 لديه تعليق يقول حلها.
  • لا يبدو أن # 36691 يحظرني ، يمكننا السماح لها بالتوسع إلى mod foo; يومًا ما في المستقبل إذا أردنا دون كسر أي شيء أعتقد.

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

يقول RFC:

قبل تثبيت الميزة ، سيتم الآن توثيق الميزات على النحو التالي:

  • سمات اللغة:

    • يجب توثيقه في مرجع الصدأ.

    • يجب أن تكون موثقة في لغة برمجة Rust.

    • قد تكون موثقة في الصدأ بالمثال.

  • يجب أن تتضمن ميزات اللغة وتغييرات المكتبة القياسية ما يلي:

    • سطر واحد للتغيير

    • ملخص أطول لإعلان الإصدار الطويل.

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

cc @ rust-lang / docs

شكرا withoutboats ! إنها أول واحدة رئيسية ، نعم. كان لدي هذا في قائمتي لأنظر إليه هذا الصباح ، وها أنت قد هزمتني به

كنت أتخيل دائمًا أن قرار الاستقرار والاستقرار الفعلي منفصلان. بمعنى أن @ rust-lang / lang يمكنه أن يقول "يمكن جعل هذا مستقرًا" ، لكن الالتزام بإزالة البوابة يضمن أيضًا وجود التوثيق. في عالم يوجد فيه الكتاب غير المستقر ، سيؤدي ذلك إلى سحب المستندات من هناك إلى المستندات المستقرة ؛ لكن حتى ذلك الحين ، الأمور محرجة بعض الشيء.

نظرًا لأن لدينا إصدارًا للتو ، كانت خطتي هي القيام بشيء كهذا:

  1. انتظر هذا لمغادرة FCP
  2. اربط بعض المستندات. (كنت أخطط لكتابتها في هذه الحالة)
  3. جعل العلاقات العامة الاستقرار.

ربما الجمع بين اثنين وثلاثة.

/ cc @ rust-lang / core ، نظرًا لأن هذه مشكلة مشتركة بين الفريق.

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

سيكون من الجيد أيضًا الحصول عليها بسرعة حتى نتمكن من ضمان وجود منفذ خلفي آمن لفرع بيتا 1.15!

إذا كنت أول من أصاب هذا ، فلن يكون الأمر بهذا السوء ولكن دعنا ندرجه ضمن الأخطاء المعروفة: استخدام ماكرو من النوع داخل بنية مع اشتقاق مخصص يتسبب في ظهور ICE https://github.com/rust-lang/ الصدأ / القضايا / 38706

https://github.com/rust-lang/rust/pull/38737 يعمل على إصلاح نوع وحدات الماكرو ICE: القلب :. أي فرصة للحصول على هذا backported إلى بيتا؟ المسوغات: يبدو من السيئ أن هناك ميزتان جديدتان بارزتان ، إحداهما تم إصدارها في 1.13 والأخرى تم إصدارها في 1.15 ، تعطّل المترجم عند استخدامهما معًا.

لقد قمت للتو بإنشاء # 38749 بخصوص توثيق الصندوق proc_macro .

لقد قرأت عدة مرات أن وحدات الماكرو 1.1 ستستقر في 1.15 ، ولكن 1.15.0-beta.1 تم شحنها منذ أسبوعين وما لا يقل عن extern crate proc_macro; لا يزال محاطًا بميزة في ذلك وكذلك في 4ecc85beb كل ليلة -12-28. هل خطة دعم تغيير الاستقرار؟

SimonSapin نعم ، كانت هذه هي الخطة ، لكننا بحاجة إلى

لا تزال هي الخطة: ص

إذا كتب المستخدم #[derive(Foo)] #[foo_def = "definition.json"] struct MyStruct; فلن يكون لدى معالج الماكرو طريقة لمعرفة ما هو "الدليل الحالي" وبالتالي لا يمكنه العثور على definition.json .

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

يمكنك الانتقال Span -> FileMap -> اسم الملف -> الدليل. كل ما ينقص هو الوصول إلى المعلومات من خلال proc_macro .

ستحتاج أيضًا إلى إخبار المترجم بإضافة تبعية إلى definition.json حتى يصبح الإصدار متسخًا إذا تم تعديله.

يمكن أن يستخدم ماكرو proc env::var("CARGO_MANIFEST_DIR") للحصول على الدليل الذي يحتوي على Cargo.toml للصندوق الذي يحتوي على استدعاء الماكرو. من المفترض أن foo_def متعلق بذلك. راجع https://github.com/dtolnay/syn/issues/70#issuecomment -268895281.

tomaka التي يمكن إجراؤها عن طريق تحويل FileMap ، على سبيل المثال هذه هي الطريقة التي يقوم بها الماكرو include_str! .

يفترض أن foo_def متعلق بذلك.

أعتقد أنه ليس من البديهي أن تضطر إلى تحديد المسار المتعلق بـ Cargo.toml.

يمكن القيام به عن طريق تعديل FileMap ، على سبيل المثال هذه هي الطريقة التي يتم بها تضمين include_str! الماكرو يفعل ذلك.

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

المعلمة هي Item . سيكون من المقبول إضافة طريقة لاسترداد مدى من هذا العنصر ، ولكن إضافة طريقة إلى Item لمطالبة المترجم بإضافة تبعية سيكون اختراق IMO.

يمكنك الانتقال إلى Span -> FileMap -> اسم الملف -> الدليل.

هل واجهات برمجة التطبيقات (على وجه الخصوص FileMap ) على مسار ليتم استقرارها؟

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

لقد حصلت للتو على هذا الخطأ في صندوق خاص بي. ماذا يحدث هنا؟

`` error: Cannot use #! [feature (proc_macro)] and #! [feature (custom_attribute)] في نفس الوقت
""

alexreg إذا كنت تستخدم #[derive] ، فهو مستقر الآن. لا تحتاج #![feature(proc_macro)] .

تضمين التغريدة
proc_macro_derive s (وحدات الماكرو 1.1) مستقرة الآن - يمكنك فقط إزالة #![feature(proc_macro)] .

هبط مؤخرًا #[proc_macro_attribute] خلف بوابة الميزة #![feature(proc_macro)] ؛ هذه غير متوافقة مع #![feature(custom_attribute)] . سيتم إهمال #![feature(custom_attribute)] بمجرد هبوط البديل (https://github.com/rust-lang/rfcs/pull/1755).

jseyfried أعتقد أنه يجب علينا تغيير مشكلة التتبع على proc_macro نظرًا لأن هذا مغلق ولا يحتوي على معلومات ذات صلة.

شكرا يا شباب. منطقي.

abonander نعم ، يجب أن يشير #![feature(proc_macro)] بالتأكيد إلى # 38356 الآن - كان يجب أن أتحقق من ذلك عند مراجعة # 38842. هل يمكنك تقديم العلاقات العامة؟

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