Remove __all__ enforcement rules out of binding phase (#5897)

## Summary

This PR moves two rules (`invalid-all-format` and `invalid-all-object`)
out of the name-binding phase, and into the dedicated pass over all
bindings that occurs at the end of the `Checker`. This is part of my
continued quest to separate the semantic model-building logic from the
actual rule enforcement.
This commit is contained in:
Charlie Marsh 2023-07-19 17:18:47 -04:00 committed by GitHub
parent b27f0fa433
commit 9834c69c98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 104 additions and 60 deletions

View file

@ -73,6 +73,18 @@ impl<'a> Binding<'a> {
self.flags.contains(BindingFlags::GLOBAL)
}
/// Return `true` if this [`Binding`] represents an assignment to `__all__` with an invalid
/// value (e.g., `__all__ = "Foo"`).
pub const fn is_invalid_all_format(&self) -> bool {
self.flags.contains(BindingFlags::INVALID_ALL_FORMAT)
}
/// Return `true` if this [`Binding`] represents an assignment to `__all__` that includes an
/// invalid member (e.g., `__all__ = ["Foo", 1]`).
pub const fn is_invalid_all_object(&self) -> bool {
self.flags.contains(BindingFlags::INVALID_ALL_OBJECT)
}
/// Return `true` if this [`Binding`] represents an unbound variable
/// (e.g., `x` in `x = 1; del x`).
pub const fn is_unbound(&self) -> bool {
@ -234,6 +246,24 @@ bitflags! {
/// x = 1
/// ```
const GLOBAL = 1 << 4;
/// The binding represents an export via `__all__`, but the assigned value uses an invalid
/// expression (i.e., a non-container type).
///
/// For example:
/// ```python
/// __all__ = 1
/// ```
const INVALID_ALL_FORMAT = 1 << 5;
/// The binding represents an export via `__all__`, but the assigned value contains an
/// invalid member (i.e., a non-string).
///
/// For example:
/// ```python
/// __all__ = [1]
/// ```
const INVALID_ALL_OBJECT = 1 << 6;
}
}