mirror of https://github.com/astral-sh/ruff
Try boxing
This commit is contained in:
parent
cd5c69b61c
commit
da8481c97d
|
|
@ -40,8 +40,10 @@ pub struct SubmoduleImportation<'a> {
|
|||
pub full_name: &'a str,
|
||||
}
|
||||
|
||||
// If we box, this goes from 48 to 16
|
||||
// If we use a u32 pointer, this goes to 8
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum BindingKind<'a> {
|
||||
pub enum BindingKind {
|
||||
Annotation,
|
||||
Argument,
|
||||
Assignment,
|
||||
|
|
@ -54,14 +56,14 @@ pub enum BindingKind<'a> {
|
|||
ClassDefinition,
|
||||
FunctionDefinition,
|
||||
// 32
|
||||
Export(Export<'a>),
|
||||
Export(u32),
|
||||
FutureImportation,
|
||||
// 40
|
||||
Importation(Importation<'a>),
|
||||
Importation(u32),
|
||||
// 48
|
||||
FromImportation(FromImportation<'a>),
|
||||
FromImportation(u32),
|
||||
// 48
|
||||
SubmoduleImportation(SubmoduleImportation<'a>),
|
||||
SubmoduleImportation(u32),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -927,10 +927,9 @@ where
|
|||
self.add_binding(
|
||||
name,
|
||||
Binding {
|
||||
kind: BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
name,
|
||||
full_name,
|
||||
}),
|
||||
kind: BindingKind::SubmoduleImportation(Box::new(
|
||||
SubmoduleImportation { name, full_name },
|
||||
)),
|
||||
runtime_usage: None,
|
||||
synthetic_usage: None,
|
||||
typing_usage: None,
|
||||
|
|
@ -954,7 +953,10 @@ where
|
|||
self.add_binding(
|
||||
name,
|
||||
Binding {
|
||||
kind: BindingKind::Importation(Importation { name, full_name }),
|
||||
kind: BindingKind::Importation(Box::new(Importation {
|
||||
name,
|
||||
full_name,
|
||||
})),
|
||||
runtime_usage: None,
|
||||
synthetic_usage: if is_explicit_reexport {
|
||||
Some((self.ctx.scope_id, alias.range()))
|
||||
|
|
@ -1307,10 +1309,10 @@ where
|
|||
self.add_binding(
|
||||
name,
|
||||
Binding {
|
||||
kind: BindingKind::FromImportation(FromImportation {
|
||||
kind: BindingKind::FromImportation(Box::new(FromImportation {
|
||||
name,
|
||||
full_name,
|
||||
}),
|
||||
})),
|
||||
runtime_usage: None,
|
||||
synthetic_usage: if is_explicit_reexport {
|
||||
Some((self.ctx.scope_id, alias.range()))
|
||||
|
|
@ -4412,13 +4414,13 @@ impl<'a> Checker<'a> {
|
|||
// import pyarrow.csv
|
||||
// print(pa.csv.read_csv("test.csv"))
|
||||
match &self.ctx.bindings[*index].kind {
|
||||
BindingKind::Importation(Importation { name, full_name })
|
||||
| BindingKind::SubmoduleImportation(SubmoduleImportation { name, full_name }) =>
|
||||
{
|
||||
BindingKind::Importation(import) => {
|
||||
let name = import.name;
|
||||
let full_name = import.full_name;
|
||||
let has_alias = full_name
|
||||
.split('.')
|
||||
.last()
|
||||
.map(|segment| &segment != name)
|
||||
.map(|segment| segment != name)
|
||||
.unwrap_or_default();
|
||||
if has_alias {
|
||||
// Mark the sub-importation as used.
|
||||
|
|
@ -4431,11 +4433,32 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
BindingKind::FromImportation(FromImportation { name, full_name }) => {
|
||||
BindingKind::SubmoduleImportation(import) => {
|
||||
let name = import.name;
|
||||
let full_name = import.full_name;
|
||||
let has_alias = full_name
|
||||
.split('.')
|
||||
.last()
|
||||
.map(|segment| &segment != name)
|
||||
.map(|segment| segment != name)
|
||||
.unwrap_or_default();
|
||||
if has_alias {
|
||||
// Mark the sub-importation as used.
|
||||
if let Some(index) = scope.get(full_name) {
|
||||
self.ctx.bindings[*index].mark_used(
|
||||
self.ctx.scope_id,
|
||||
expr.range(),
|
||||
context,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
BindingKind::FromImportation(import) => {
|
||||
let name = import.name;
|
||||
let full_name = &import.full_name;
|
||||
let has_alias = full_name
|
||||
.split('.')
|
||||
.last()
|
||||
.map(|segment| segment != name)
|
||||
.unwrap_or_default();
|
||||
if has_alias {
|
||||
// Mark the sub-importation as used.
|
||||
|
|
@ -4665,10 +4688,8 @@ impl<'a> Checker<'a> {
|
|||
// Grab the existing bound __all__ values.
|
||||
if let StmtKind::AugAssign { .. } = &parent.node {
|
||||
if let Some(index) = scope.get("__all__") {
|
||||
if let BindingKind::Export(Export { names: existing }) =
|
||||
&self.ctx.bindings[*index].kind
|
||||
{
|
||||
names.extend_from_slice(existing);
|
||||
if let BindingKind::Export(export) = &self.ctx.bindings[*index].kind {
|
||||
names.extend(&export.names);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4693,7 +4714,7 @@ impl<'a> Checker<'a> {
|
|||
self.add_binding(
|
||||
id,
|
||||
Binding {
|
||||
kind: BindingKind::Export(Export { names: all_names }),
|
||||
kind: BindingKind::Export(Box::new(Export { names: all_names })),
|
||||
runtime_usage: None,
|
||||
synthetic_usage: None,
|
||||
typing_usage: None,
|
||||
|
|
@ -4981,7 +5002,7 @@ impl<'a> Checker<'a> {
|
|||
.get("__all__")
|
||||
.map(|index| &self.ctx.bindings[*index])
|
||||
.and_then(|binding| match &binding.kind {
|
||||
BindingKind::Export(Export { names }) => Some((names, binding.range)),
|
||||
BindingKind::Export(export) => Some((&export.names, binding.range)),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
|
|
@ -5013,7 +5034,7 @@ impl<'a> Checker<'a> {
|
|||
.get("__all__")
|
||||
.map(|index| &self.ctx.bindings[*index])
|
||||
.and_then(|binding| match &binding.kind {
|
||||
BindingKind::Export(Export { names }) => Some((names.as_slice(), binding.range)),
|
||||
BindingKind::Export(export) => Some((export.names.as_slice(), binding.range)),
|
||||
_ => None,
|
||||
});
|
||||
|
||||
|
|
@ -5223,14 +5244,9 @@ impl<'a> Checker<'a> {
|
|||
let binding = &self.ctx.bindings[*index];
|
||||
|
||||
let full_name = match &binding.kind {
|
||||
BindingKind::Importation(Importation { full_name, .. }) => full_name,
|
||||
BindingKind::FromImportation(FromImportation { full_name, .. }) => {
|
||||
full_name.as_str()
|
||||
}
|
||||
BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
full_name,
|
||||
..
|
||||
}) => full_name,
|
||||
BindingKind::Importation(import) => import.full_name,
|
||||
BindingKind::FromImportation(import) => import.full_name.as_str(),
|
||||
BindingKind::SubmoduleImportation(import) => import.full_name,
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ impl Violation for RuntimeImportInTypeCheckingBlock {
|
|||
/// TCH004
|
||||
pub fn runtime_import_in_type_checking_block(binding: &Binding) -> Option<Diagnostic> {
|
||||
let full_name = match &binding.kind {
|
||||
BindingKind::Importation(Importation { full_name, .. }) => full_name,
|
||||
BindingKind::FromImportation(FromImportation { full_name, .. }) => full_name.as_str(),
|
||||
BindingKind::SubmoduleImportation(SubmoduleImportation { full_name, .. }) => full_name,
|
||||
BindingKind::Importation(import) => import.full_name,
|
||||
BindingKind::FromImportation(import) => import.full_name.as_str(),
|
||||
BindingKind::SubmoduleImportation(import) => import.full_name,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -161,66 +161,67 @@ impl Violation for TypingOnlyStandardLibraryImport {
|
|||
|
||||
/// Return `true` if `this` is implicitly loaded via importing `that`.
|
||||
fn is_implicit_import(this: &Binding, that: &Binding) -> bool {
|
||||
match &this.kind {
|
||||
BindingKind::Importation(Importation {
|
||||
full_name: this_name,
|
||||
..
|
||||
})
|
||||
| BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
name: this_name, ..
|
||||
}) => match &that.kind {
|
||||
BindingKind::FromImportation(FromImportation {
|
||||
full_name: that_name,
|
||||
..
|
||||
}) => {
|
||||
// Ex) `pkg.A` vs. `pkg`
|
||||
this_name
|
||||
.rfind('.')
|
||||
.map_or(false, |i| this_name[..i] == *that_name)
|
||||
}
|
||||
BindingKind::Importation(Importation {
|
||||
full_name: that_name,
|
||||
..
|
||||
})
|
||||
| BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
name: that_name, ..
|
||||
}) => {
|
||||
// Ex) `pkg.A` vs. `pkg.B`
|
||||
this_name == that_name
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
BindingKind::FromImportation(FromImportation {
|
||||
full_name: this_name,
|
||||
..
|
||||
}) => match &that.kind {
|
||||
BindingKind::Importation(Importation {
|
||||
full_name: that_name,
|
||||
..
|
||||
})
|
||||
| BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
name: that_name, ..
|
||||
}) => {
|
||||
// Ex) `pkg.A` vs. `pkg`
|
||||
this_name
|
||||
.rfind('.')
|
||||
.map_or(false, |i| &this_name[..i] == *that_name)
|
||||
}
|
||||
BindingKind::FromImportation(FromImportation {
|
||||
full_name: that_name,
|
||||
..
|
||||
}) => {
|
||||
// Ex) `pkg.A` vs. `pkg.B`
|
||||
this_name.rfind('.').map_or(false, |i| {
|
||||
that_name
|
||||
.rfind('.')
|
||||
.map_or(false, |j| this_name[..i] == that_name[..j])
|
||||
})
|
||||
}
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
true
|
||||
// match &this.kind {
|
||||
// BindingKind::Importation(Importation {
|
||||
// full_name: this_name,
|
||||
// ..
|
||||
// })
|
||||
// | BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
// name: this_name, ..
|
||||
// }) => match &that.kind {
|
||||
// BindingKind::FromImportation(FromImportation {
|
||||
// full_name: that_name,
|
||||
// ..
|
||||
// }) => {
|
||||
// // Ex) `pkg.A` vs. `pkg`
|
||||
// this_name
|
||||
// .rfind('.')
|
||||
// .map_or(false, |i| this_name[..i] == *that_name)
|
||||
// }
|
||||
// BindingKind::Importation(Importation {
|
||||
// full_name: that_name,
|
||||
// ..
|
||||
// })
|
||||
// | BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
// name: that_name, ..
|
||||
// }) => {
|
||||
// // Ex) `pkg.A` vs. `pkg.B`
|
||||
// this_name == that_name
|
||||
// }
|
||||
// _ => false,
|
||||
// },
|
||||
// BindingKind::FromImportation(FromImportation {
|
||||
// full_name: this_name,
|
||||
// ..
|
||||
// }) => match &that.kind {
|
||||
// BindingKind::Importation(Importation {
|
||||
// full_name: that_name,
|
||||
// ..
|
||||
// })
|
||||
// | BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
// name: that_name, ..
|
||||
// }) => {
|
||||
// // Ex) `pkg.A` vs. `pkg`
|
||||
// this_name
|
||||
// .rfind('.')
|
||||
// .map_or(false, |i| &this_name[..i] == *that_name)
|
||||
// }
|
||||
// BindingKind::FromImportation(FromImportation {
|
||||
// full_name: that_name,
|
||||
// ..
|
||||
// }) => {
|
||||
// // Ex) `pkg.A` vs. `pkg.B`
|
||||
// this_name.rfind('.').map_or(false, |i| {
|
||||
// that_name
|
||||
// .rfind('.')
|
||||
// .map_or(false, |j| this_name[..i] == that_name[..j])
|
||||
// })
|
||||
// }
|
||||
// _ => false,
|
||||
// },
|
||||
// _ => false,
|
||||
// }
|
||||
}
|
||||
|
||||
/// Return `true` if `name` is exempt from typing-only enforcement.
|
||||
|
|
@ -257,9 +258,9 @@ pub fn typing_only_runtime_import(
|
|||
}
|
||||
|
||||
let full_name = match &binding.kind {
|
||||
BindingKind::Importation(Importation { full_name, .. }) => full_name,
|
||||
BindingKind::FromImportation(FromImportation { full_name, .. }) => full_name.as_str(),
|
||||
BindingKind::SubmoduleImportation(SubmoduleImportation { full_name, .. }) => full_name,
|
||||
BindingKind::Importation(import) => import.full_name,
|
||||
BindingKind::FromImportation(import) => import.full_name.as_str(),
|
||||
BindingKind::SubmoduleImportation(import) => import.full_name,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -85,11 +85,8 @@ pub fn check_call(checker: &mut Checker, func: &Expr) {
|
|||
// irrelevant bindings (like non-Pandas imports).
|
||||
if let ExprKind::Name { id, .. } = &value.node {
|
||||
if checker.ctx.find_binding(id).map_or(true, |binding| {
|
||||
if let BindingKind::Importation(Importation {
|
||||
full_name: module, ..
|
||||
}) = &binding.kind
|
||||
{
|
||||
module != &"pandas"
|
||||
if let BindingKind::Importation(import) = &binding.kind {
|
||||
import.full_name != "pandas"
|
||||
} else {
|
||||
matches!(
|
||||
binding.kind,
|
||||
|
|
|
|||
|
|
@ -59,45 +59,28 @@ impl<'a> Binding<'a> {
|
|||
|
||||
pub fn redefines(&self, existing: &'a Binding) -> bool {
|
||||
match &self.kind {
|
||||
BindingKind::Importation(Importation { full_name, .. }) => {
|
||||
if let BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
full_name: existing,
|
||||
..
|
||||
}) = &existing.kind
|
||||
{
|
||||
return full_name == existing;
|
||||
BindingKind::Importation(import) => {
|
||||
if let BindingKind::SubmoduleImportation(existing) = &existing.kind {
|
||||
return import.full_name == existing.full_name;
|
||||
}
|
||||
}
|
||||
BindingKind::FromImportation(FromImportation { full_name, .. }) => {
|
||||
if let BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
full_name: existing,
|
||||
..
|
||||
}) = &existing.kind
|
||||
{
|
||||
return full_name == existing;
|
||||
BindingKind::FromImportation(import) => {
|
||||
if let BindingKind::SubmoduleImportation(existing) = &existing.kind {
|
||||
return import.full_name == existing.full_name;
|
||||
}
|
||||
}
|
||||
BindingKind::SubmoduleImportation(SubmoduleImportation { full_name, .. }) => {
|
||||
match &existing.kind {
|
||||
BindingKind::Importation(Importation {
|
||||
full_name: existing,
|
||||
..
|
||||
})
|
||||
| BindingKind::SubmoduleImportation(SubmoduleImportation {
|
||||
full_name: existing,
|
||||
..
|
||||
}) => {
|
||||
return full_name == existing;
|
||||
}
|
||||
BindingKind::FromImportation(FromImportation {
|
||||
full_name: existing,
|
||||
..
|
||||
}) => {
|
||||
return full_name == existing;
|
||||
}
|
||||
_ => {}
|
||||
BindingKind::SubmoduleImportation(import) => match &existing.kind {
|
||||
BindingKind::Importation(existing) => {
|
||||
return import.full_name == existing.full_name;
|
||||
}
|
||||
}
|
||||
BindingKind::SubmoduleImportation(existing) => {
|
||||
return import.full_name == existing.full_name;
|
||||
}
|
||||
BindingKind::FromImportation(existing) => {
|
||||
return import.full_name == existing.full_name;
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
BindingKind::Annotation => {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -259,11 +242,11 @@ pub enum BindingKind<'a> {
|
|||
Builtin,
|
||||
ClassDefinition,
|
||||
FunctionDefinition,
|
||||
Export(Export<'a>),
|
||||
Export(Box<Export<'a>>),
|
||||
FutureImportation,
|
||||
Importation(Importation<'a>),
|
||||
FromImportation(FromImportation<'a>),
|
||||
SubmoduleImportation(SubmoduleImportation<'a>),
|
||||
Importation(Box<Importation<'a>>),
|
||||
FromImportation(Box<FromImportation<'a>>),
|
||||
SubmoduleImportation(Box<SubmoduleImportation<'a>>),
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
|
|
|||
|
|
@ -166,10 +166,8 @@ impl<'a> Context<'a> {
|
|||
return None;
|
||||
};
|
||||
match &binding.kind {
|
||||
BindingKind::Importation(Importation {
|
||||
full_name: name, ..
|
||||
})
|
||||
| BindingKind::SubmoduleImportation(SubmoduleImportation { name, .. }) => {
|
||||
BindingKind::Importation(import) => {
|
||||
let name = import.full_name;
|
||||
if name.starts_with('.') {
|
||||
if let Some(module) = &self.module_path {
|
||||
let mut source_path = from_relative_import(module, name);
|
||||
|
|
@ -188,9 +186,28 @@ impl<'a> Context<'a> {
|
|||
Some(source_path)
|
||||
}
|
||||
}
|
||||
BindingKind::FromImportation(FromImportation {
|
||||
full_name: name, ..
|
||||
}) => {
|
||||
BindingKind::SubmoduleImportation(import) => {
|
||||
let name = import.name;
|
||||
if name.starts_with('.') {
|
||||
if let Some(module) = &self.module_path {
|
||||
let mut source_path = from_relative_import(module, name);
|
||||
if source_path.is_empty() {
|
||||
None
|
||||
} else {
|
||||
source_path.extend(call_path.into_iter().skip(1));
|
||||
Some(source_path)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
let mut source_path: CallPath = from_unqualified_name(name);
|
||||
source_path.extend(call_path.into_iter().skip(1));
|
||||
Some(source_path)
|
||||
}
|
||||
}
|
||||
BindingKind::FromImportation(import) => {
|
||||
let name = &import.full_name;
|
||||
if name.starts_with('.') {
|
||||
if let Some(module) = &self.module_path {
|
||||
let mut source_path = from_relative_import(module, name);
|
||||
|
|
@ -243,16 +260,19 @@ impl<'a> Context<'a> {
|
|||
// Ex) Given `module="sys"` and `object="exit"`:
|
||||
// `import sys` -> `sys.exit`
|
||||
// `import sys as sys2` -> `sys2.exit`
|
||||
BindingKind::Importation(Importation { name, full_name }) => {
|
||||
if full_name == &module {
|
||||
BindingKind::Importation(import) => {
|
||||
if import.full_name == module {
|
||||
// Verify that `sys` isn't bound in an inner scope.
|
||||
if self
|
||||
.scopes()
|
||||
.take(scope_index)
|
||||
.all(|scope| scope.get(name).is_none())
|
||||
.all(|scope| scope.get(import.name).is_none())
|
||||
{
|
||||
if let Some(source) = binding.source {
|
||||
return Some((self.stmts[source], format!("{name}.{member}")));
|
||||
return Some((
|
||||
self.stmts[source],
|
||||
format!("{}.{member}", import.name),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -260,17 +280,22 @@ impl<'a> Context<'a> {
|
|||
// Ex) Given `module="os.path"` and `object="join"`:
|
||||
// `from os.path import join` -> `join`
|
||||
// `from os.path import join as join2` -> `join2`
|
||||
BindingKind::FromImportation(FromImportation { name, full_name }) => {
|
||||
if let Some((target_module, target_member)) = full_name.split_once('.') {
|
||||
BindingKind::FromImportation(import) => {
|
||||
if let Some((target_module, target_member)) =
|
||||
import.full_name.split_once('.')
|
||||
{
|
||||
if target_module == module && target_member == member {
|
||||
// Verify that `join` isn't bound in an inner scope.
|
||||
if self
|
||||
.scopes()
|
||||
.take(scope_index)
|
||||
.all(|scope| scope.get(name).is_none())
|
||||
.all(|scope| scope.get(import.name).is_none())
|
||||
{
|
||||
if let Some(source) = binding.source {
|
||||
return Some((self.stmts[source], (*name).to_string()));
|
||||
return Some((
|
||||
self.stmts[source],
|
||||
(*import.name).to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -278,16 +303,19 @@ impl<'a> Context<'a> {
|
|||
}
|
||||
// Ex) Given `module="os"` and `object="name"`:
|
||||
// `import os.path ` -> `os.name`
|
||||
BindingKind::SubmoduleImportation(SubmoduleImportation { name, .. }) => {
|
||||
if name == &module {
|
||||
BindingKind::SubmoduleImportation(import) => {
|
||||
if import.name == module {
|
||||
// Verify that `os` isn't bound in an inner scope.
|
||||
if self
|
||||
.scopes()
|
||||
.take(scope_index)
|
||||
.all(|scope| scope.get(name).is_none())
|
||||
.all(|scope| scope.get(import.name).is_none())
|
||||
{
|
||||
if let Some(source) = binding.source {
|
||||
return Some((self.stmts[source], format!("{name}.{member}")));
|
||||
return Some((
|
||||
self.stmts[source],
|
||||
format!("{}.{member}", import.name),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue