PERLMROAPI(1perl)

πŸ“¦
version 5.44.0 Β· 2 versions
, in arch rolling

πŸ’– perlmroapi β€” the Perl method resolution plugin interface πŸ’–

okay so bestie, this is the manual page from the Perl Programmers Reference Guide (that's the 1perl section, iykyk) and it's literally about letting you swap out how Perl figures out which parent class comes next. it's giving pluggable MRO realness. periodt. πŸ‘‘


✨ DESCRIPTION ✨

so here's the tea 🍡 β€” as of Perl 5.10.1 there's a whole new interface for plugging in and using method resolution orders other than the default one (that's plain old linear depth first search). and the C3 method resolution order that showed up back in 5.10.0? yeah, that got re-implemented as a plugin, and the best part is the Perl-space interface didn't change at all. iconic behaviour, honestly. πŸ’…

every plugin has to register itself by handing over this exact structure:

struct mro_alg {
    AV *(*resolve)(pTHX_ HV *stash, U32 level);
    const char *name;
    U16 length;
    U16 kflags;
    U32 hash;
};

and then it calls Perl_mro_register, like so:

Perl_mro_register(aTHX_ &my_mro_alg);

and now, the field-by-field vibe check πŸ”:

  • resolve β€” a pointer to the linearisation function. it's described further down, keep scrolling bestie.
  • name β€” the name of the MRO. either in ISO-8859-1 or UTF-8, your call.
  • length β€” the length of that name. yes, you gotta say it out loud. πŸ“
  • kflags β€” if your name is given in UTF-8, set this to HVhek_UTF8. the value gets passed direct as the parameter kflags to hv_common(). no filter, no nothing.
  • hash β€” a precomputed hash value for the MRO's name, or 0. that's it, that's the whole field. zero is a perfectly valid mood. ✨

πŸŽ€ Callbacks πŸŽ€

the resolve function is the one that actually gets called to generate a linearised ISA for a given stash, using your MRO. it shows up with a pointer to the stash, and a level of 0. and listen β€” the core always sets level to 0 when it calls your function. the parameter is only there so your implementation can track depth if it needs to recurse. so don't come for that zero, it's not personal. 😌

your function should return a reference to an array containing string SVs that give the names of the parent classes, in order. and those class names? they should be the result of calling HvENAME() on the stash. in those cases where HvENAME() returns null, you use HvNAME() instead. that's the rule, no cap.

⚠️ real talk, bestie: the caller is responsible for incrementing the reference count of the array returned if it wants to keep the structure. so if you created a temporary value and you're keeping no pointer to it, call sv_2mortal() to make sure it gets disposed of correctly. but if you've cached your return value, then just return a pointer to it without changing the reference count. do not skip this part, the refcount police are real. 🚨

πŸ’œ Caching πŸ’œ

computing MROs can be expensive, and not in the fun designer way. 😭 so the implementation hands you a cache, and in it you can store a single SV * β€” or literally anything that can be cast to SV *, like AV *. versatile queen.

to read your private value, use the macro MRO_GET_PRIVATE_DATA(), passing it the mro_meta structure from the stash and a pointer to your mro_alg structure:

meta = HvMROMETA(stash);
private_sv = MRO_GET_PRIVATE_DATA(meta, &my_mro_alg);

to set your private value, call Perl_mro_set_private_data():

Perl_mro_set_private_data(aTHX_ meta, &c3_alg, private_sv);

and here's the important bit 🫢 β€” the private data cache will take ownership of a reference to private_sv, much the same way that hv_store() takes ownership of a reference to the value that you pass it. so plan accordingly, she takes what's hers.


🌈 Examples 🌈

want to see actual MRO implementations in the wild? go peek at S_mro_get_linear_isa_c3() and the "BOOT:" section of ext/mro/mro.xs, plus S_mro_get_linear_isa_dfs() in mro_core.c. study material, fr fr. πŸ“š


πŸ‘‘ AUTHORS πŸ‘‘

the implementation of the C3 MRO and the switchable MROs inside the perl core was written by Brandon L Black. Nicholas Clark created the pluggable interface, refactored Brandon's implementation so it works with it, and wrote this very document. two legends, one interface. slay. πŸ’–


okay that's the whole page, you ate it, you understood it, you're basically a core contributor now πŸ¦‹

<cute>this was perl v5.44.0, dated 2026-10-17, and it's the manual page for PERLMROAPI(1perl) β€” go forth and register your MRO, bestie πŸ’…βœ¨</cute>

πŸ“¦ where this page comes from
  • arch rolling: perl 5.44.0-1 Β· Artistic-1.0-Perl AND GPL-1.0-or-later
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms