PERLMROAPI(1)

✨ PERLMROAPI(1) ✨

okay bestie so this is the Perl Programmers Reference Guide page perlmroapi β€” like, the manual for the Perl method resolution plugin interface. yes it's C-adjacent. yes it's giving scary. but we're gonna get through it together πŸ’–


🌸 NAME 🌸

perlmroapi β€” the Perl method resolution plugin interface. that's it, that's the name, slay.


πŸ¦‹ DESCRIPTION πŸ¦‹

so, as of Perl 5.10.1 there's a whole new interface for plugging in and using method resolution orders that are not the default one (the default being linear depth first search, iykyk). the C3 method resolution order that showed up back in 5.10.0 got <em>re-implemented</em> as a plugin, and the Perl-space interface didn't change even a little bit. iconic behavior honestly.

every plugin has to register itself by handing over this struct:

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

and then calling Perl_mro_register:

Perl_mro_register(aTHX_ &my_mro_alg);

now let's break down the fields one by one, no skipping, we don't do that here 🫢

πŸŽ€ resolve

pointer to the linearisation function β€” it's described down below in Callbacks, keep scrolling bestie.

πŸŽ€ name

the name of the MRO. either in ISO-8859-1 or UTF-8. your pick.

πŸŽ€ length

the length of the name. yeah. it does what it says πŸ’…

πŸŽ€ kflags

if the name is given in UTF-8, set this to HVhek_UTF8. the value gets passed <em>direct</em> as the parameter kflags to hv_common(). no middleman, no vibes check.

πŸŽ€ hash

a precomputed hash value for the MRO's name, or 0. that's the whole thing.


🌈 Callbacks 🌈

the resolve function is the one that gets called to generate a linearised ISA for the given stash, using this MRO. it gets called with a pointer to the stash, and a level of 0.

here's the thing: the core <em>always</em> sets level to 0 when it calls your function. the parameter exists purely so your implementation can track depth if it needs to recurse. so like, don't panic about it 🫢

your function should return a reference to an array containing string SVs that give the names of the parent classes <em>in order</em>. and the names of the classes should be the result of calling HvENAME() on the stash. in those cases where HvENAME() returns null, you use HvNAME() instead. periodt.

⚠️ the caller is responsible for incrementing the reference count of the array returned if it wants to keep the structure. so if you've created a temporary value that you keep no pointer to, use sv_2mortal() to make sure it gets disposed of correctly. if you've cached your return value, then return a pointer to it <em>without</em> changing the reference count. do not skip this, bestie, this is the kind of thing that eats your memory alive 😭

πŸ’œ Caching πŸ’œ

computing MROs can be <em>expensive</em>, lowkey tragic. so the implementation gives you a cache, and in that cache you can store a single SV *, or literally anything that can be cast to SV *, such as AV *.

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 lore: the private data cache will <strong>take ownership of a reference to <code>private_sv</code></strong>, much the same way that hv_store() takes ownership of a reference to the value that you pass it. so like… it's yours but also it's not anymore. main character energy tbh πŸ‘‘


⭐ Examples ⭐

want to see actual MRO implementations in the wild? go look at:

  • S_mro_get_linear_isa_c3() and the "BOOT:" section of ext/mro/mro.xs
  • S_mro_get_linear_isa_dfs() in mro_core.c

read those, they're the blueprint fr fr.


πŸ‘‘ AUTHORS πŸ‘‘

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


okay that's the whole page, you ate that πŸŽ€

this was brought to you by perl v5.42.3, dated 2026-08-03 β€” mwah, see you in the next manpage bestie πŸ’…βœ¨πŸ¦‹

πŸ“¦ where this page comes from