Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions crates/perry-transform/src/inline/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,20 @@ pub fn method_lookup_is_unshadowed(classes: &[Class], class_name: &str, method_n
return false;
};

// Index classes by name for O(1) chain-walk lookups instead of an
// O(classes) linear scan per level. `entry().or_insert` keeps the FIRST
// class for a duplicate name, matching the prior `iter().find()` semantics
// (duplicate class names occur cross-module, e.g. Effect's same-named
// `Type` in SchemaAST and ParseResult).
let mut by_name: HashMap<&str, &Class> = HashMap::with_capacity(classes.len());
for c in classes {
by_name.entry(c.name.as_str()).or_insert(c);
}

let mut cur = Some(class_name);
let mut depth = 0usize;
while let Some(name) = cur {
let Some(class) = classes.iter().find(|c| c.name == name) else {
let Some(class) = by_name.get(name).copied() else {
return false;
};
if class.extends_expr.is_some() || class.native_extends.is_some() {
Expand Down Expand Up @@ -308,10 +318,16 @@ pub fn class_chain_property_sets(
let mut fields = HashSet::new();
let mut getters = HashSet::new();
let mut setters = HashSet::new();
// Index by name for O(1) chain-walk lookups; `entry().or_insert` keeps the
// first class for a duplicate name, matching the prior `iter().find()`.
let mut by_name: HashMap<&str, &Class> = HashMap::with_capacity(classes.len());
for c in classes {
by_name.entry(c.name.as_str()).or_insert(c);
}
let mut cur = Some(class_name);
let mut depth = 0usize;
while let Some(name) = cur {
let class = classes.iter().find(|c| c.name == name)?;
let class = by_name.get(name).copied()?;
if class.extends_expr.is_some() || class.native_extends.is_some() {
return None;
}
Expand Down