-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[red-knot] Rename and rework the CoreStdlibModule
enum
#15071
Conversation
pub fn try_from_file_and_symbol( | ||
db: &'db dyn Db, | ||
file: File, | ||
instance_name: &str, | ||
) -> Option<Self> { | ||
let candidate = match instance_name { | ||
"Any" => Self::Any, | ||
"ClassVar" => Self::ClassVar, | ||
"Deque" => Self::Deque, | ||
"List" => Self::List, | ||
"Dict" => Self::Dict, | ||
"DefaultDict" => Self::DefaultDict, | ||
"Set" => Self::Set, | ||
"FrozenSet" => Self::FrozenSet, | ||
"Counter" => Self::Counter, | ||
"ChainMap" => Self::ChainMap, | ||
"OrderedDict" => Self::OrderedDict, | ||
"Optional" => Self::Optional, | ||
"Union" => Self::Union, | ||
"NoReturn" => Self::NoReturn, | ||
"Tuple" => Self::Tuple, | ||
"Type" => Self::Type, | ||
"Callable" => Self::Callable, | ||
"Annotated" => Self::Annotated, | ||
"Literal" => Self::Literal, | ||
"Never" => Self::Never, | ||
"Self" => Self::TypingSelf, | ||
"Final" => Self::Final, | ||
"Unpack" => Self::Unpack, | ||
"Required" => Self::Required, | ||
"TypeAlias" => Self::TypeAlias, | ||
"TypeGuard" => Self::TypeGuard, | ||
"TypeIs" => Self::TypeIs, | ||
"ReadOnly" => Self::ReadOnly, | ||
"Concatenate" => Self::Concatenate, | ||
"NotRequired" => Self::NotRequired, | ||
"LiteralString" => Self::LiteralString, | ||
_ => return None, | ||
}; | ||
|
||
candidate | ||
.check_module(file_to_module(db, file)?.known()?) | ||
.then_some(candidate) | ||
} | ||
|
||
/// Return `true` if `module` is a module from which this `KnownInstance` variant can validly originate. | ||
/// | ||
/// Most variants can only exist in one module, which is the same as `self.class().canonical_module()`. | ||
/// Some variants could validly be defined in either `typing` or `typing_extensions`, however. | ||
pub fn check_module(self, module: KnownModule) -> bool { | ||
match self { | ||
Self::Any | ||
| Self::ClassVar | ||
| Self::Deque | ||
| Self::List | ||
| Self::Dict | ||
| Self::DefaultDict | ||
| Self::Set | ||
| Self::FrozenSet | ||
| Self::Counter | ||
| Self::ChainMap | ||
| Self::OrderedDict | ||
| Self::Optional | ||
| Self::Union | ||
| Self::NoReturn | ||
| Self::Tuple | ||
| Self::Type | ||
| Self::Callable => module.is_typing(), | ||
Self::Annotated | ||
| Self::Literal | ||
| Self::LiteralString | ||
| Self::Never | ||
| Self::TypingSelf | ||
| Self::Final | ||
| Self::Concatenate | ||
| Self::Unpack | ||
| Self::Required | ||
| Self::NotRequired | ||
| Self::TypeAlias | ||
| Self::TypeGuard | ||
| Self::TypeIs | ||
| Self::ReadOnly | ||
| Self::TypeAliasType(_) | ||
| Self::TypeVar(_) => { | ||
matches!(module, KnownModule::Typing | KnownModule::TypingExtensions) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is functionally the same, but in the try_from*()
methods on the other Known*
enums, we delay the file_to_module()
call as much as possible, as it's probably much more expensive than match
ing on the value of a string. This PR does the same for this method.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is beautiful, what a nice simplification and unification of concepts.
1% speedup on the incremental benchmark... who knows if that's real, but certainly better than a slowdown whatever the case 😆 https://codspeed.io/astral-sh/ruff/branches/alex%2Fknown-module |
Summary
This PR does several things:
CoreStdlibModule
enum toKnownModule
, since it is a parallel enum toKnownClass
,KnownFunction
andKnownInstanceType
stdlib.rs
tomodule_resolver::module.rs
. This allows it to be stored as a field onModuleInner
objects, and retrieved using a getter method fromModule
objects. This in turn means that we can then addknown()
andis_known()
methods to theModule
struct, which allows us to query whether a givenModule
represents a known module in much the same way we already do usingFunctionType::is_known
andClass::is_known
.These changes have several goals:
Known*
enumsModule
really represents a specific module from the standard library. We had the same checks written out in several places, which was error-prone, since there are several things that needed to be checked and some are quite subtle. (One recent example: [red-knot] Statically known branches #15019 (comment).)definition.rs
are an example)Test Plan
cargo test -p red_knot_python_semantic
. No new tests added -- this should be a pure refactor.