You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rust emits different error messages on recent nightlies. This commit
adjusts the first post for those messages.
The new error messages were introduced in
rust-lang/rust#116343
Reported in
#997 (comment)
Copy file name to clipboardExpand all lines: blog/content/edition-2/posts/01-freestanding-rust-binary/index.ar.md
+24-15Lines changed: 24 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -118,10 +118,16 @@ fn main() {}
118
118
```
119
119
> cargo build
120
120
error: `#[panic_handler]` function required, but not found
121
-
error: language item required, but not found: `eh_personality`
121
+
error: unwinding panics are not supported without std
122
122
```
123
123
124
-
الآن يفتقد المترجم إلى دالة `#[panic_handler]` و_عنصر اللغة_ (language item).
124
+
الآن يفتقد المترجم إلى دالة `#[panic_handler]` ويشتكي من أن _الفك_ (unwinding) غير ممكن بدون المكتبة القياسية. سننظر في كلا الخطأين في الأقسام التالية.
125
+
126
+
<divclass="note">
127
+
128
+
في سلاسل أدوات Rust الأقدم، يظهر الخطأ الثاني بدلاً من ذلك كـ `language item required, but not found: eh_personality`، والذي له نفس سبب خطأ `unwinding panics are not supported without std`.
عناصر اللغة هي عناصر خاصة (سمات ودوال وأنواع وما إلى ذلك) مطلوبة داخليًا من قِبَل المترجم. على سبيل المثال، سمة [`Copy`] هي عنصر لغة يخبر المترجم بالأنواع التي لها [_دلالات النسخ_][`Copy`]. عند النظر إلى [التنفيذ][copy code]، نرى أنه يحتوي على السمة الخاصة `#[lang = "copy"]` التي تعرّفه كعنصر لغة.
158
+
يستخدم Rust [فك تسلسل المكدس][stack unwinding] بشكل افتراضي لتشغيل المدمِّرات لجميع متغيرات المكدس الحية في حالة حدوث [panic]. هذا يضمن تحرير جميع الذاكرة المستخدمة ويسمح للخيط الرئيسي بالتقاط الـ panic ومواصلة التنفيذ. ومع ذلك، فإن الفك عملية معقدة وتتطلب بعض المكتبات الخاصة بنظام التشغيل (مثل [libunwind] على Linux أو [معالجة الاستثناءات المنظمة][structured exception handling] على Windows)، والتي تتطلب مكتبة Rust القياسية. والنتيجة هي أننا لا نستطيع استخدام الفك لنواة نظام التشغيل `no_std` الخاصة بنا.
في حين أن توفير تنفيذات مخصصة لعناصر اللغة ممكن، إلا أنه يجب القيام بذلك فقط كملاذ أخير. والسبب هو أن عناصر اللغة هي تفاصيل تنفيذ غير مستقرة للغاية ولا يتم التحقق من أنواعها حتى (أي أن المترجم لا يتحقق حتى مما إذا كانت الدالة تحتوي على أنواع الوسيطات الصحيحة). لحسن الحظ، هناك طريقة أكثر استقرارًا لإصلاح خطأ عنصر اللغة أعلاه.
162
+
خطأ `language item required, but not found: eh_personality` في سلاسل أدوات Rust الأقدم يشير أيضًا إلى الفك. يُميِّز [عنصر اللغة `eh_personality`][`eh_personality` language item] الدالة التي يجب استخدامها لتنفيذ فك تسلسل المكدس. عناصر اللغة هي عناصر خاصة (سمات ودوال وأنواع وما إلى ذلك) مطلوبة داخليًا من قِبَل المترجم. في سلاسل أدوات Rust الأحدث، تم تحسين رسالة الخطأ لتجنب ذكر تفصيل التنفيذ هذا.
158
163
159
-
يُميِّز [عنصر اللغة `eh_personality`][`eh_personality` language item] دالة تُستخدم لتنفيذ [فك تسلسل المكدس][stack unwinding]. بشكل افتراضي، يستخدم Rust الفك لتشغيل المدمِّرات لجميع متغيرات المكدس الحية في حالة حدوث [panic]. هذا يضمن تحرير جميع الذاكرة المستخدمة ويسمح للخيط الرئيسي بالتقاط الـ panic ومواصلة التنفيذ. ومع ذلك، فإن الفك عملية معقدة وتتطلب بعض المكتبات الخاصة بنظام التشغيل (مثل [libunwind] على Linux أو [معالجة الاستثناءات المنظمة][structured exception handling] على Windows)، لذا لا نريد استخدامها لنظام التشغيل الخاص بنا.
164
+
</div>
160
165
161
166
[`eh_personality` language item]: https://github.com/rust-lang/rust/blob/edb368491551a77d77a48446d4ee88b35490c565/src/libpanic_unwind/gcc.rs#L11-L45
يضبط هذا استراتيجية الـ panic على `abort` لكل من ملف التعريف `dev` (المستخدم لـ `cargo build`) وملف التعريف `release` (المستخدم لـ `cargo build --release`). الآن لم يعد عنصر اللغة `eh_personality` مطلوبًا.
183
+
يضبط هذا استراتيجية الـ panic على `abort` لكل من ملف التعريف `dev` (المستخدم لـ `cargo build`) وملف التعريف `release` (المستخدم لـ `cargo build --release`). الآن يجب أن يكون خطأ `unwinding panics are not supported without std` قد أُصلح.
179
184
180
185
[abort on panic]: https://github.com/rust-lang/rust/pull/32900
181
186
182
-
الآن أصلحنا كلا الخطأين أعلاه. ومع ذلك، إذا حاولنا تجميعه الآن، يحدث خطأ آخر:
187
+
إذا حاولنا تجميعه الآن، يحدث خطأ جديد:
183
188
184
189
```
185
190
> cargo build
186
-
error: requires `start` lang_item
191
+
error: using `fn main` requires the standard library
187
192
```
188
193
189
-
يفتقر برنامجنا إلى عنصر اللغة `start`، الذي يعرّف نقطة الدخول.
194
+
<divclass="note">
195
+
196
+
تُبلِّغ سلاسل أدوات Rust الأقدم عن هذا كـ `error: requires start lang_item` بدلاً من ذلك. يعرّف عنصر اللغة `start` نقطة الدخول الأساسية التي تستدعي دالة `main` لاحقًا. لذا فإن هذا الخطأ له نفس سبب خطأ ``using `fn main` requires the standard library`` في سلاسل الأدوات الأحدث.
197
+
198
+
</div>
190
199
191
-
## سمة `start`
200
+
## نقطة الدخول
192
201
193
-
قد يظن المرء أن دالة `main` هي أول دالة تُستدعى عند تشغيل برنامج. ومع ذلك، فإن معظم اللغات لديها [نظام وقت تشغيل][runtime system] مسؤول عن أشياء مثل جمع القمامة (مثلاً في Java) أو خيوط البرمجيات (مثلاً goroutines في Go). يحتاج وقت التشغيل هذا إلى الاستدعاء قبل `main`، لأنه يحتاج إلى تهيئة نفسه.
202
+
قد يظن المرء أن دالة `main` هي "نقطة الدخول" للبرنامج، أي أول دالة تُستدعى عند تشغيل برنامج. ومع ذلك، فإن معظم اللغات لديها [نظام وقت تشغيل][runtime system] مسؤول عن أشياء مثل جمع القمامة (مثلاً في Java) أو خيوط البرمجيات (مثلاً goroutines في Go). يحتاج وقت التشغيل هذا إلى الاستدعاء قبل `main`، لأنه يحتاج إلى تهيئة نفسه.
في ثنائي Rust نموذجي يربط المكتبة القياسية، يبدأ التنفيذ في مكتبة وقت تشغيل C تسمى `crt0` ("C runtime zero")، والتي تُهيئ البيئة لتطبيق C. يتضمن ذلك إنشاء مكدس ووضع الوسيطات في السجلات الصحيحة. ثم يستدعي وقت تشغيل C [نقطة دخول وقت تشغيل Rust][rt::lang_start]، والمميَّزة بعنصر اللغة `start`. يمتلك Rust وقت تشغيل بسيطًا للغاية يعتني ببعض الأشياء الصغيرة مثل إعداد حراس فائض المكدس أو طباعة تتبع المكدس عند الـ panic. ثم يستدعي وقت التشغيل أخيرًا دالة `main`.
لا يمتلك ملفنا القابل للتنفيذ المستقل وصولاً إلى وقت تشغيل Rust و`crt0`، لذا نحتاج إلى تعريف نقطة الدخول الخاصة بنا. تنفيذ عنصر اللغة `start` لن يساعد، لأنه سيتطلب `crt0` أيضًا. بدلاً من ذلك، نحتاج إلى الكتابة فوق نقطة دخول `crt0` مباشرةً.
210
+
لا يمتلك ملفنا القابل للتنفيذ المستقل وصولاً إلى وقت تشغيل Rust و`crt0`، لذا نحتاج إلى تعريف نقطة الدخول الخاصة بنا ولا يمكننا فقط تعريف دالة `main`.
Copy file name to clipboardExpand all lines: blog/content/edition-2/posts/01-freestanding-rust-binary/index.es.md
+24-15Lines changed: 24 additions & 15 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -117,10 +117,16 @@ fn main() {}
117
117
```
118
118
> cargo build
119
119
error: `#[panic_handler]` function required, but not found
120
-
error: language item required, but not found: `eh_personality`
120
+
error: unwinding panics are not supported without std
121
121
```
122
122
123
-
Ahora el compilador indica que falta una función `#[panic_handler]` y un _elemento de lenguaje_ (_language item_).
123
+
Ahora el compilador indica que falta una función `#[panic_handler]` y se queja de que el _unwinding_ no es posible sin la biblioteca estándar. Examinaremos ambos errores en las siguientes secciones.
124
+
125
+
<divclass="note">
126
+
127
+
En versiones antiguas de las toolchains de Rust, el segundo error dice en su lugar `language item required, but not found: eh_personality`, que tiene la misma causa que el error `unwinding panics are not supported without std`.
128
+
129
+
</div>
124
130
125
131
## Implementación de Panic
126
132
@@ -146,16 +152,15 @@ El [parámetro `PanicInfo`][PanicInfo] contiene el archivo y la línea donde ocu
Los elementos de lenguaje son elementos especiales (traits, funciones, tipos, etc.) que el compilador requiere internamente. Por ejemplo, el trait [`Copy`]es un elemento de lenguaje que indica al compilador qué tipos tienen [_semántica de copia_][`Copy`]. Si observamos su [implementación][copy code], veremos que tiene el atributo especial `#[lang = "copy"]`, que lo define como un elemento de lenguaje.
157
+
Rust utiliza el [desenrollado de pila][stack unwinding] por defecto para ejecutar los destructores de todas las variables de pila activas en caso de un [pánico][panic]. Esto asegura que toda la memoria utilizada sea liberada y permite que el hilo principal capture el pánico y continúe su ejecución. Sin embargo, el unwinding es un proceso complicado y requiere algunas bibliotecas específicas del sistema operativo (por ejemplo, [libunwind] en Linux o [manejadores estructurados de excepciones][structured exception handling] en Windows), que requieren la biblioteca estándar de Rust. La consecuencia es que no podemos usar unwinding para nuestro kernel de sistema operativo `no_std`.
Aunque es posible proporcionar implementaciones personalizadas de elementos de lenguaje, esto debería hacerse solo como último recurso. La razón es que los elementos de lenguaje son detalles de implementación altamente inestables y ni siquiera están verificados por tipos (el compilador no comprueba si una función tiene los tipos de argumento correctos). Afortunadamente, hay una forma más estable de solucionar el error relacionado con el elemento de lenguaje mencionado.
161
+
El error `language item required, but not found: eh_personality` en versiones antiguas de las toolchains de Rust también apunta al unwinding. El [elemento de lenguaje `eh_personality`][`eh_personality` language item] marca la función que debe usarse para implementar el desenrollado de pila. Los elementos de lenguaje son elementos especiales (traits, funciones, tipos, etc.) que el compilador requiere internamente. En versiones más recientes de las toolchains de Rust, el mensaje de error se mejoró para evitar mencionar este detalle de implementación.
157
162
158
-
El [elemento de lenguaje `eh_personality`][`eh_personality` language item] marca una función utilizada para implementar el [desenrollado de pila][stack unwinding]. Por defecto, Rust utiliza unwinding para ejecutar los destructores de todas las variables de pila activas en caso de un [pánico][panic]. Esto asegura que toda la memoria utilizada sea liberada y permite que el hilo principal capture el pánico y continúe ejecutándose. Sin embargo, el unwinding es un proceso complicado y requiere algunas bibliotecas específicas del sistema operativo (por ejemplo, [libunwind] en Linux o [manejadores estructurados de excepciones][structured exception handling] en Windows), por lo que no queremos usarlo en nuestro sistema operativo.
163
+
</div>
159
164
160
165
[`eh_personality` language item]: https://github.com/rust-lang/rust/blob/edb368491551a77d77a48446d4ee88b35490c565/src/libpanic_unwind/gcc.rs#L11-L45
Esto establece la estrategia de pánico en `abort` tanto para el perfil `dev` (utilizado en `cargo build`) como para el perfil `release` (utilizado en `cargo build --release`). Ahora, el elemento de lenguaje `eh_personality` ya no debería ser necesario.
183
+
Esto establece la estrategia de pánico en `abort` tanto para el perfil `dev` (utilizado en `cargo build`) como para el perfil `release` (utilizado en `cargo build --release`). Ahora, el error `unwinding panics are not supported without std`debería estar solucionado.
179
184
180
185
[abort on panic]: https://github.com/rust-lang/rust/pull/32900
181
186
182
-
Ahora hemos solucionado ambos errores anteriores. Sin embargo, si intentamos compilarlo ahora, ocurre otro error:
187
+
Si intentamos compilarlo ahora, ocurre un nuevo error:
183
188
184
189
```
185
190
> cargo build
186
-
error: requires `start` lang_item
191
+
error: using `fn main` requires the standard library
187
192
```
188
193
189
-
Nuestro programa carece del elemento de lenguaje `start`, que define el punto de entrada.
194
+
<divclass="note">
195
+
196
+
En versiones antiguas de las toolchains de Rust, esto se reporta como `error: requires start lang_item` en su lugar. El elemento de lenguaje `start` define el punto de entrada subyacente que luego llama a la función `main`. Por lo tanto, este error tiene la misma causa que el error ``using `fn main` requires the standard library`` en versiones más recientes de las toolchains.
197
+
198
+
</div>
190
199
191
-
## El Atributo `start`
200
+
## Punto de Entrada
192
201
193
-
Podría pensarse que la función `main` es la primera que se ejecuta al correr un programa. Sin embargo, la mayoría de los lenguajes tienen un [sistema de tiempo de ejecución][runtime system], encargado de tareas como la recolección de basura (por ejemplo, en Java) o los hilos de software (por ejemplo, goroutines en Go). Este sistema de tiempo de ejecución necesita ejecutarse antes de `main`, ya que debe inicializarse.
202
+
Podría pensarse que la función `main` es el "punto de entrada" del programa, es decir, la primera función que se ejecuta al correr un programa. Sin embargo, la mayoría de los lenguajes tienen un [sistema de tiempo de ejecución][runtime system], encargado de tareas como la recolección de basura (por ejemplo, en Java) o los hilos de software (por ejemplo, goroutines en Go). Este sistema de tiempo de ejecución necesita ejecutarse antes de `main`, ya que debe inicializarse.
En un binario típico de Rust que enlaza con la biblioteca estándar, la ejecución comienza en una biblioteca de tiempo de ejecución de C llamada `crt0` ("C runtime zero"), que configura el entorno para una aplicación en C. Esto incluye la creación de una pila y la colocación de los argumentos en los registros adecuados. Luego, el tiempo de ejecución de C invoca el [punto de entrada del tiempo de ejecución de Rust][rt::lang_start], que está marcado por el elemento de lenguaje `start`. Rust tiene un tiempo de ejecución muy minimalista, que se encarga de tareas menores como configurar los guardias de desbordamiento de pila o imprimir un backtrace en caso de pánico. Finalmente, el tiempo de ejecución llama a la función `main`.
Nuestro ejecutable autónomo no tiene acceso al tiempo de ejecución de Rust ni a `crt0`, por lo que necesitamos definir nuestro propio punto de entrada. Implementar el elemento de lenguaje `start`no ayudaría, ya que aún requeriría `crt0`. En su lugar, debemos sobrescribir directamente el punto de entrada de `crt0`.
210
+
Nuestro ejecutable autónomo no tiene acceso al tiempo de ejecución de Rust ni a `crt0`, por lo que necesitamos definir nuestro propio punto de entrada y no podemos simplemente definir una función `main`.
0 commit comments