Try boxing

This commit is contained in:
Charlie Marsh 2023-05-06 23:39:06 -04:00
parent cd5c69b61c
commit da8481c97d
7 changed files with 188 additions and 161 deletions

View File

@ -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() {

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,

View File

@ -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::SubmoduleImportation(import) => match &existing.kind {
BindingKind::Importation(existing) => {
return import.full_name == existing.full_name;
}
BindingKind::FromImportation(FromImportation {
full_name: existing,
..
}) => {
return full_name == existing;
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! {

View File

@ -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),
));
}
}
}