I haven't read the text of PEP 267 in a quite a while ;-). At some point, we worked out a scheme that was completely backwards compatible.
Alas, it wasn't recorded in the PEP.
There are quite a few ways to change shadowing (exec object in dict, change a base class, etc).
About all they have in common is that they should be rare.
from __future__ import noshadow
If a name (or its immediately enclosing class) is explicitly declared dynamic, semantics are the same as today.
For all other names, the compiler may assume that the nearest enclosing binding of this name will always be in the same namespace. (Names need not all be in a single namespace, but once a particular name is found, that namespace will always be the correct place to look for that name.)
Results are undefined if the name is later unbound in that namespace or shadowed by a nearer enclosing namespace.
Question: Should the compiler be able to assume the same *object* (=can bind as local), or only the same namespace (=can do with a single indirection, perhaps sped up with a variant of DLict).
Question: Is there any reason that this should apply only to builtins, rather than to any namespace?
Objection: Users can do something undefined and get "normal" results instead of a warning -- on their own platform. They can even do this strictly through changes to other modules which do not themselves import noshadow. How serious is this objection?
If a warning is required, will the bookkeeping be needed even in release mode, or will it be an option depending on compiler settings? Should the compiler decline to take advantage of its freedom if it finds a namespace without noshadow somewhere in the lookup chain?