Can you flesh this out for what stumbled into being my running
example? That is, how could a regexp pattern object be part of a
cycle?

Let me try to remember when we saw this problem in the past, but
on first sigh, it seems that indeed that cannot happen in the regular case.

And, in general, I can't add attributes to p, or change their bindings:

That's after the changes to add a new Py_TPFLAGS_IMMUTABLETYPE flag, which predates the
creation of the issue we are discussing. But in general, new heap types are not immutable by
For instance, in python3.8:

>>> array.array.x = 4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'array.array'

but in python 3.10.0a7 (before Py_TPFLAGS_IMMUTABLETYPE):

Python 3.10.0a7 (tags/v3.10.0a7:53e55290cf, May 27 2021, 20:20:26) [Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import array
>>> instance = array.array("f")
>>> type = array.array
>>> type.instance = instance

On Thu, 27 May 2021 at 20:15, Tim Peters <tim.peters@gmail.com> wrote:
[Tim]
>> And if a type pointer is the only thing being visited, then there's no point
>> unless the object can itself be reachable from the type object.

{Pablo]
> But that could happen easily for heap types as they are mutable by
> default. For instance, you set the instance in a global:
>
> type -> module -> globals -> instance -> type

Sorry, but this is apparently a rat's nest and that's too sketchy for me ;-)

Can you flesh this out for what stumbled into being my running
example? That is, how could a regexp pattern object be part of a
cycle?

>>> import re
>>> p = re.compile("ab*c")
>>> type(p)
<class 're.Pattern'>
>>> type(p).__module__
're'
>>> type(type(p).__module__)
<class 'str'>

That is, its __module__ attribute is a string, not a module object.

And, in general, I can't add attributes to p, or change their bindings:

>>> p.flags
32
>>> p.flags = re
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: readonly attribute
>>> p.newattr = re
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 're.Pattern' object has no attribute 'newattr'

I just don't see a way to trick it into being part of a cycle.

Not denying that safe is better than sorry, though.