gh-109118: Make comprehensions work within annotation scopes, but without inlining by JelleZijlstra · Pull Request #118160 · python/cpython (original) (raw)

I looked at this a bit, and my initial conclusions aren't promising. I think this may not really be possible to support, at least not without extensive hackery.

If we consider this test case:

            class C[T]:
                T = "class"
                class Inner[U](make_base([T for _ in (1,)]), make_base(T)):
                    pass

The problem is that in the annotation scope of Inner, there is already a reference to T (in make_base(T)). The goal of this PR is to inline the comprehension [T for _ in (1,)] into that same scope, but somehow have the inlined T symbol behave differently from the existing T symbol in the same scope. Since all symbol information is tracked by name, that would require renaming the inlined T, somehow tracking that the renamed symbol is "really" named T, and extending that knowledge into the compiler. That sounds quite painful.

I think the more feasible options are either to disable comprehension inlining in annotation scopes, or to accept that the visibility effects of comprehension inlining leak here.

Given that comprehension inlining is usually transparent, and that complex code in annotation scopes is unlikely, I think just disabling comprehension inlining in this case is reasonable.

(If I had a time machine, I think I would inline comprehensions only in function scopes and nowhere else, as I'd initially proposed in the first version of PEP 709.)