Skip to content

Commit 2eb3687

Browse files
committed
Propagate ResourcePool lease types in HIR
1 parent d73fd67 commit 2eb3687

4 files changed

Lines changed: 253 additions & 28 deletions

File tree

src/checks/body.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,13 @@ fn check_resource_pool_lease_stmt(analyzer: &mut Analyzer<'_>, statement: &HirSt
509509
}
510510

511511
fn is_resource_pool_borrow(callee: &Callee) -> bool {
512-
matches!(callee, Callee::Qualified { namespace, name } if namespace == "ResourcePool" && name == "borrow")
512+
matches!(callee, Callee::Qualified { namespace, name } if type_root_name(namespace) == "ResourcePool" && name == "borrow")
513+
}
514+
515+
fn type_root_name(type_name: &str) -> &str {
516+
type_name
517+
.split_once('<')
518+
.map_or(type_name, |(root, _)| root)
513519
}
514520

515521
fn resource_is_active_at(

src/checks/local.rs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ struct LocalFlowStep {
9595
kind: LocalFlowStepKind,
9696
uses: Vec<(String, Span)>,
9797
binding: Option<LocalFlowBinding>,
98-
resource_binding: Option<String>,
98+
resource_binding: Option<LocalFlowResourceBinding>,
9999
events: Vec<HirEffectEvent>,
100100
successors: Vec<LocalFlowEdge>,
101101
}
@@ -108,6 +108,12 @@ struct LocalFlowBinding {
108108
value_ident: Option<(String, Span)>,
109109
}
110110

111+
#[derive(Debug, Clone, PartialEq, Eq)]
112+
struct LocalFlowResourceBinding {
113+
name: String,
114+
type_name: Option<String>,
115+
}
116+
111117
#[derive(Debug, Clone, PartialEq, Eq)]
112118
struct LocalFlowEdge {
113119
to: usize,
@@ -1484,7 +1490,10 @@ fn transfer_flow_step(step: &LocalFlowStep, mut state: BodyState) -> BodyState {
14841490
}
14851491
}
14861492
if let Some(resource_binding) = &step.resource_binding {
1487-
state.bind_resource(resource_binding.clone());
1493+
state.bind_resource(resource_binding.name.clone());
1494+
if let Some(type_name) = &resource_binding.type_name {
1495+
state.record_type(resource_binding.name.clone(), type_name.clone());
1496+
}
14881497
}
14891498

14901499
state.apply_retention_events(&step.events);
@@ -1606,9 +1615,14 @@ fn local_flow_step_binding(statement: &HirStmt) -> Option<LocalFlowBinding> {
16061615
}
16071616
}
16081617

1609-
fn local_flow_step_resource_binding(statement: &HirStmt) -> Option<String> {
1618+
fn local_flow_step_resource_binding(statement: &HirStmt) -> Option<LocalFlowResourceBinding> {
16101619
match statement {
1611-
HirStmt::With { binding, .. } => Some(binding.clone()),
1620+
HirStmt::With {
1621+
binding, resource, ..
1622+
} => Some(LocalFlowResourceBinding {
1623+
name: binding.clone(),
1624+
type_name: hir_expr_type_name(resource).map(str::to_string),
1625+
}),
16121626
HirStmt::Let { .. }
16131627
| HirStmt::Return { .. }
16141628
| HirStmt::If { .. }
@@ -1620,6 +1634,20 @@ fn local_flow_step_resource_binding(statement: &HirStmt) -> Option<String> {
16201634
}
16211635
}
16221636

1637+
fn hir_expr_type_name(expr: &HirExpr) -> Option<&str> {
1638+
match expr {
1639+
HirExpr::Ident { type_name, .. }
1640+
| HirExpr::Call { type_name, .. }
1641+
| HirExpr::Effect { type_name, .. }
1642+
| HirExpr::Manage { type_name, .. } => type_name.as_deref(),
1643+
HirExpr::Field { access, .. } => access.type_name.as_deref(),
1644+
HirExpr::Number { .. }
1645+
| HirExpr::String { .. }
1646+
| HirExpr::Closure { .. }
1647+
| HirExpr::Unknown(_) => None,
1648+
}
1649+
}
1650+
16231651
fn hir_stmt_span(statement: &HirStmt) -> &Span {
16241652
match statement {
16251653
HirStmt::Let { span, .. }
@@ -2324,6 +2352,12 @@ mod tests {
23242352
.flow_entry_state(&span(2))
23252353
.is_some_and(|state| state.is_resource("file"))
23262354
);
2355+
assert_eq!(
2356+
local_analysis
2357+
.flow_entry_state(&span(2))
2358+
.and_then(|state| state.value_type("file")),
2359+
Some("File")
2360+
);
23272361
assert!(
23282362
local_analysis
23292363
.flow_entry_state(&span(3))

0 commit comments

Comments
 (0)