Skip to content
Merged
Show file tree
Hide file tree
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
13 changes: 13 additions & 0 deletions crates/perry-hir/src/destructuring/var_decl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,19 @@ pub(crate) fn lower_var_decl_with_destructuring(
None if !is_var_decl => Some(Expr::Undefined),
other => other,
};
// Remember `const x = { … }` bindings whose initializer became a
// closed-shape record class. That is the only proof available that
// every property of `x` is a data field rather than an accessor —
// `is_closed_shape` rejects getters and setters — and the
// loop-invariant property hoist refuses to fire without it.
if !mutable {
if let Some(Expr::New { class_name, .. }) = init.as_ref() {
if class_name.starts_with("__AnonShape_") {
ctx.closed_shape_literal_locals
.insert(id, class_name.clone());
}
}
}
result.push(Stmt::Let {
id,
name,
Expand Down
5 changes: 5 additions & 0 deletions crates/perry-hir/src/lower/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ impl LoweringContext {
mixin_funcs: HashMap::new(),
anon_shape_classes: HashMap::new(),
anon_shape_fields: HashMap::new(),
closed_shape_literal_locals: HashMap::new(),
prefer_exported_method_shape_seed: false,
forward_class_names: std::collections::HashSet::new(),
forward_class_decl_depth: std::collections::HashMap::new(),
Expand Down Expand Up @@ -987,6 +988,10 @@ impl LoweringContext {
self.locals.lookup_type(name)
}

pub(crate) fn lookup_local_type_by_id(&self, id: LocalId) -> Option<&Type> {
self.locals.lookup_type_by_id(id)
}

pub(crate) fn lookup_func(&self, name: &str) -> Option<FuncId> {
self.functions_index
.get(name)
Expand Down
10 changes: 10 additions & 0 deletions crates/perry-hir/src/lower/locals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ impl Locals {
}

/// `Type` of the innermost binding named `name`, if any. O(1).
/// Type of the innermost binding carrying `id`. Needed when a
/// transform holds a `LocalId` from already-lowered HIR and has no name.
pub(crate) fn lookup_type_by_id(&self, id: LocalId) -> Option<&Type> {
self.entries
.iter()
.rev()
.find(|(_, entry_id, _)| *entry_id == id)
.map(|(_, _, ty)| ty)
}

pub(crate) fn lookup_type(&self, name: &str) -> Option<&Type> {
self.lookup_index(name).map(|i| &self.entries[i].2)
}
Expand Down
9 changes: 9 additions & 0 deletions crates/perry-hir/src/lower/lowering_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,15 @@ pub struct LoweringContext {
/// (e.g. recognizing a bundled mysql2 `createPool(config)` by its option
/// names) recovers them here.
pub(crate) anon_shape_fields: HashMap<String, Vec<String>>,
/// `const x = { … }` bindings whose initializer lowered to a closed-shape
/// record class (`__AnonShape_*`), mapped to that class name. Membership
/// is a proof that every property of `x` is a DATA field: `is_closed_shape`
/// rejects getters and setters, so reading one is side-effect free. The
/// loop-invariant property hoist needs exactly that guarantee, and cannot
/// get it from the binding's TYPE — a getter-bearing literal infers as
/// `Any`, but an *annotated* structural object type can still be backed by
/// an accessor.
pub(crate) closed_shape_literal_locals: HashMap<LocalId, String>,
/// Set while lowering a directly exported binding/default expression.
/// Eligible method literals consume this flag and retain the seeded IIFE
/// representation needed to publish an exact cross-module own-method
Expand Down
1 change: 1 addition & 0 deletions crates/perry-hir/src/lower/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ pub(crate) use lowering_context::{
};

mod locals;
pub(crate) mod property_array_hoist;
pub(crate) use locals::Locals;

mod typed_parse;
Expand Down
Loading
Loading