תקרת אורך מזהה (Identifier too long)#

ניסוח המקור#

perl5-upstream/pod/perlvar.pod קובע, בקטע Syntax of Variable Names:

שמות משתנים ב־Perl יכולים להיות בפורמטים מספר. בדרך כלל, עליהם להתחיל באות או קו תחתון, ובמקרה זה הם יכולים להיות באורך שרירותי (עד מגבלה פנימית של 251 תווים) ועשויים להכיל אותיות, ספרות, קווים תחתונים, או הרצף המיוחד :: או '.

ניסוח זה מטעה משתי בחינות.

תיקון#

הקביעה הנכונה, נכון לסדרת היציבה Perl 5.42, היא:

מזהים יכולים להיות באורך של עד 251 בתים. שמות החורגים מאורך זה גורמים לשגיאה בזמן ניתוח התחביר: Identifier too long.

שני דברים חשוב להבין מכך:

  1. בתים, לא תווים. התקרה נמדדת בבתים של ייצוג המקור, לא בנקודות קוד של Unicode. מזהי UTF-8 מגיעים לפיכך לגבול בפחות תווים:

    רוחב תו

    התקבל אחרון

    נדחה ראשון

    1 בית (ASCII)

    251 תווים

    252 תווים

    2 בתים (למשל é)

    125 תווים

    126 תווים

    3 בתים (למשל )

    83 תווים

    84 תווים

    4 בתים (למשל 𐌰 - גותית)

    62 תווים

    63 תווים

    בכל מקרה הדחייה מתרחשת כאשר אורך הבתים חורג לראשונה מ־251. ה־“251 תווים“ בטקסט המקור נכון רק עבור מקרה ה־ASCII.

  2. שגיאה קשה, לא ”מגבלה פנימית“. הניסוח ”עד מגבלה פנימית“ מרמז על משהו רך. זה לא - מנתח התחביר של perl5 מעלה חריגה פטאלית Identifier too long. ההודעה היא הדבר היחיד שהמשתמש רואה; אין קיצוץ, אזהרה, או נסיגה.

הסיבה הקרובה ב־5.42 היא ה־buffer ‏tokenbuf[256] ב־state של מנתח התחביר, יחד עם e = dest_end - 3 (בית sigil + ‏\0 בסוף + שולי בטיחות) הנלקחים בחשבון בתוך S_parse_ident. הצירוף מניב 252 בתים בסך הכל פחות sigil = 251 בתים של שם המזהה עצמו.

המקור blead כבר הגדיל את התקרה#

ללא קשר ל־errata זה, פיתוח perl5 (לאחר 5.42) כבר הגדיל את התקרה. ה־commit ‏8785c114b5 (”parser.h Allow up to 256 characters in a token“), המופיע לראשונה ב־development tag v5.43.4, מחליף את ה־tokenbuf בן 256 הבתים ב־buffer בן 1024 בתים. סדרת היציבה הבאה (Perl 5.44) צפויה לפיכך לאפשר מזהים באורך של עד כ־1020 בתים כברירת מחדל. תקרת 251 הבתים היא מאפיין של 5.42 ומה שלפניה.

pperl behavior#

pperl is the c2rust transpilation of perl5’s C interpreter. Its identifier-length behavior is:

אורך

perl5 5.42.2

pperl

251 בתים

מקבל

מקבל

252 בתים

דוחה

מקבל (סטייה)

1019 בתים

דוחה

מקבל (סטייה)

1020 בתים

דוחה

דוחה

1024 בתים

דוחה

דוחה

הסטייה אמיתית וניתנת לראייה מקוד המשתמש. הסיבה אינה ב־transpilation של c2rust עצמו. פלט c2rust הוא שיקוף נאמן, שורה־לשורה, של מקור ה־C המוזן לו. הסיבה היא drift של ה־upstream-checkout: ‏perl5-upstream/ מוצמד כעת ל־snapshot של blead (לאחר 5.43.4) ולא ל־maintenance tag של 5.42.x. ל־blead יש את ה־tokenbuf המוגדל - שיקוף c2rust יורש אותו.

This is an instance of a broader category of latent divergences: upstream blead has accumulated 140+ commits to toke.c alone since the 5.42.2 tag, and the same arithmetic - whatever blead does is what pperl does - applies to every one of them. Other likely-affected areas (parser-visible only):

  • qr/.../xx משופר ‏(PPC 0026) נוחת ב־blead; הטיפול ברווחים/הערות בתוך character classes שונה מ־5.42.

  • intuit_more bug fixes (multiple commits): edge cases in $foo[bar] vs $foo{bar} ambiguity resolution behave better in pperl than in 5.42.

  • שכתוב API של S_parse_ident: מיקום השגיאה המדווח על ידי שגיאות תחביר הקשורות במזהים זז בין 5.42 ו־blead.

הפתרון אינו תיקון פלט c2rust; אלא הצמדת perl5-upstream/ ל־v5.42.2 והרצה מחדש של pipeline ה־transpile.

Until that is done, pperl is - strictly speaking - ”perl5 next“ rather than ”perl5 5.42 stable“. For most user code this is invisible; for the corner cases above, behavior matches blead, not 5.42.

בדיקות#

בדיקות התאימות המכסות errata זה נמצאות ב:

  • t/01-parsing/090-identifier-length-ascii.t

  • t/01-parsing/091-identifier-length-utf8.t

They probe the boundary at 251 bytes (ASCII and 2/3/4-byte UTF-8) and at the upstream-blead secondary cutoff near 1024 bytes. Each subtest encodes a perl5 5.42 expectation; pperl currently fails subsets of the suite as documented above. The failing subtests are the operational tracking record for this errata entry.