Skip to content

Commit 6f3ab55

Browse files
committed
Use HIR call resolution in body checks
1 parent b2b0e40 commit 6f3ab55

2 files changed

Lines changed: 43 additions & 42 deletions

File tree

src/analyzer.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::checks;
22
use crate::diagnostic::{Diagnostic, Span, code};
3-
use crate::hir::{CallResolution, DuplicateSymbolKind, FunctionSig, Hir, HirTypeKind};
3+
use crate::hir::{CallResolution, DuplicateSymbolKind, Hir, HirTypeKind};
44
use crate::lexer::{Token, lex};
55
use crate::syntax::ast::{Callee, EffectDecl, Item};
66
use crate::syntax::parse_source;
@@ -168,15 +168,6 @@ impl Analyzer<'_> {
168168
}
169169
}
170170

171-
pub(crate) fn resolve_callee(&self, callee: &Callee) -> Option<&FunctionSig> {
172-
match callee {
173-
Callee::Name(name) => self.hir.resolve_function(None, name),
174-
Callee::Qualified { namespace, name } => {
175-
self.hir.resolve_function(Some(namespace), name)
176-
}
177-
}
178-
}
179-
180171
pub(crate) fn resolve_call_site(&self, callee: &Callee, span: &Span) -> CallResolution {
181172
self.hir
182173
.call_resolution(span)

src/checks/body.rs

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet};
22

33
use crate::analyzer::Analyzer;
44
use crate::diagnostic::{Diagnostic, code};
5+
use crate::hir::{CallResolution, HirTypeKind, ResolvedCalleeKind};
56
use crate::syntax::ast::{
67
Block, CallArg, Callee, DataEffect, Expr, FunctionDecl, Item, LetKind, Stmt,
78
};
@@ -342,8 +343,10 @@ fn apply_expr_effects(analyzer: &mut Analyzer<'_>, expr: &Expr, state: &mut Body
342343
apply_expr_effects(analyzer, value, state);
343344
}
344345
Expr::Effect { value, .. } => apply_expr_effects(analyzer, value, state),
345-
Expr::Call { callee, args, .. } => {
346-
apply_retention_effects(analyzer, callee, args, state);
346+
Expr::Call {
347+
callee, args, span, ..
348+
} => {
349+
apply_retention_effects(analyzer, callee, span, args, state);
347350
for arg in args {
348351
apply_expr_effects(analyzer, &arg.value, state);
349352
}
@@ -360,21 +363,23 @@ fn apply_expr_effects(analyzer: &mut Analyzer<'_>, expr: &Expr, state: &mut Body
360363
fn apply_retention_effects(
361364
analyzer: &Analyzer<'_>,
362365
callee: &Callee,
366+
span: &crate::diagnostic::Span,
363367
args: &[CallArg],
364368
state: &mut BodyState,
365369
) {
366-
let Some(signature) = analyzer.resolve_callee(callee) else {
367-
return;
370+
let retained_params = match analyzer.resolve_call_site(callee, span) {
371+
CallResolution::Resolved { signature, .. } => signature.retained_params,
372+
CallResolution::EnumVariant | CallResolution::Unknown => return,
368373
};
369-
if signature.retained_params.is_empty() {
374+
if retained_params.is_empty() {
370375
return;
371376
}
372377

373378
for arg in args {
374379
let Some(name) = &arg.name else {
375380
continue;
376381
};
377-
if !signature.retained_params.contains(name) {
382+
if !retained_params.contains(name) {
378383
continue;
379384
}
380385
if let Expr::Effect {
@@ -577,8 +582,10 @@ fn check_resource_escape_expr(analyzer: &mut Analyzer<'_>, binding: &str, expr:
577582
check_resource_escape_expr(analyzer, binding, value);
578583
}
579584
Expr::Effect { value, .. } => check_resource_escape_expr(analyzer, binding, value),
580-
Expr::Call { callee, args, .. } => {
581-
check_resource_retained_by_call(analyzer, binding, callee, args);
585+
Expr::Call {
586+
callee, args, span, ..
587+
} => {
588+
check_resource_retained_by_call(analyzer, binding, callee, span, args);
582589
for arg in args {
583590
check_resource_escape_expr(analyzer, binding, &arg.value);
584591
}
@@ -593,15 +600,16 @@ fn check_resource_retained_by_call(
593600
analyzer: &mut Analyzer<'_>,
594601
binding: &str,
595602
callee: &Callee,
603+
span: &crate::diagnostic::Span,
596604
args: &[CallArg],
597605
) {
598-
let Some(signature) = analyzer.resolve_callee(callee) else {
599-
return;
606+
let retained_params = match analyzer.resolve_call_site(callee, span) {
607+
CallResolution::Resolved { signature, .. } => signature.retained_params,
608+
CallResolution::EnumVariant | CallResolution::Unknown => return,
600609
};
601-
if signature.retained_params.is_empty() {
610+
if retained_params.is_empty() {
602611
return;
603612
}
604-
let retained_params = signature.retained_params.clone();
605613

606614
for arg in args {
607615
let Some(name) = &arg.name else {
@@ -702,13 +710,20 @@ fn check_fresh_return(
702710
);
703711
}
704712
Expr::Call { callee, span, .. } => {
705-
let constructor_is_struct = match callee {
706-
Callee::Name(name) => is_struct_type(analyzer, name),
707-
Callee::Qualified { .. } => false,
713+
let resolution = analyzer.resolve_call_site(callee, span);
714+
let constructor_is_struct = matches!(
715+
resolution,
716+
CallResolution::Resolved {
717+
kind: ResolvedCalleeKind::Constructor {
718+
type_kind: HirTypeKind::Struct
719+
},
720+
..
721+
}
722+
);
723+
let call_returns_fresh = match resolution {
724+
CallResolution::Resolved { signature, .. } => signature.returns_fresh,
725+
CallResolution::EnumVariant | CallResolution::Unknown => false,
708726
};
709-
let call_returns_fresh = analyzer
710-
.resolve_callee(callee)
711-
.is_some_and(|signature| signature.returns_fresh);
712727
if !constructor_is_struct && !call_returns_fresh {
713728
analyzer.diagnostics.push(
714729
Diagnostic::warning(
@@ -781,7 +796,7 @@ fn infer_expr_type(analyzer: &Analyzer<'_>, expr: &Expr, state: &BodyState) -> O
781796
Expr::Effect { value, .. } | Expr::Manage { value, .. } => {
782797
infer_expr_type(analyzer, value, state)
783798
}
784-
Expr::Call { callee, .. } => infer_call_type(analyzer, callee),
799+
Expr::Call { callee, span, .. } => infer_call_type(analyzer, callee, span),
785800
Expr::Field { base, name, .. } => {
786801
let base_type = infer_expr_type(analyzer, base, state)?;
787802
let field = analyzer.hir.type_info(&base_type)?.fields.get(name)?;
@@ -791,19 +806,14 @@ fn infer_expr_type(analyzer: &Analyzer<'_>, expr: &Expr, state: &BodyState) -> O
791806
}
792807
}
793808

794-
fn infer_call_type(analyzer: &Analyzer<'_>, callee: &Callee) -> Option<String> {
795-
if let Some(signature) = analyzer.resolve_callee(callee)
796-
&& let Some(return_type) = &signature.return_type
797-
{
798-
return Some(return_type.clone());
799-
}
800-
801-
match callee {
802-
Callee::Name(name) if analyzer.hir.type_info(name).is_some() => Some(name.clone()),
803-
Callee::Qualified { namespace, name } if name == "new" => {
804-
analyzer.hir.type_info(namespace).map(|_| namespace.clone())
805-
}
806-
Callee::Name(_) | Callee::Qualified { .. } => None,
809+
fn infer_call_type(
810+
analyzer: &Analyzer<'_>,
811+
callee: &Callee,
812+
span: &crate::diagnostic::Span,
813+
) -> Option<String> {
814+
match analyzer.resolve_call_site(callee, span) {
815+
CallResolution::Resolved { signature, .. } => signature.return_type,
816+
CallResolution::EnumVariant | CallResolution::Unknown => None,
807817
}
808818
}
809819

0 commit comments

Comments
 (0)