Skip to content

Commit

Permalink
fix: only resolve direct methods in annotations and improve errors
Browse files Browse the repository at this point in the history
  • Loading branch information
jac3km4 committed Feb 8, 2024
1 parent fcb6389 commit 19c42a2
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 12 deletions.
11 changes: 10 additions & 1 deletion compiler/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ pub enum Cause {
if .1.len() > MAX_RESOLUTION_ERRORS {"\n...and more"} else {""}
)]
NoMatchingOverload(Ident, Box<[FunctionMatchError]>),
#[error(
"this signature does not match any existing method, make sure that the function qualifiers
and argument types are correct"
)]
NoMethodWithMatchingSignature,
#[error("no method with this name exists on the target type")]
NoMethodWithMatchingName,
}

impl Cause {
Expand All @@ -118,7 +125,9 @@ impl Cause {
| Self::InvalidIntrinsicUse(_, _)
| Self::UnificationFailed(_, _) => "TYPE_ERR",
Self::FunctionNotFound(_) => "UNRESOLVED_FN",
Self::MethodNotFound(_, _) => "UNRESOLVED_METHOD",
Self::MethodNotFound(_, _) | Self::NoMethodWithMatchingSignature | Self::NoMethodWithMatchingName => {
"UNRESOLVED_METHOD"
}
Self::MemberNotFound(_, _) => "UNRESOLVED_MEMBER",
Self::ClassNotFound(_) | Self::UnresolvedType(_) => "UNRESOLVED_TYPE",
Self::UnresolvedReference(_) => "UNRESOLVED_REF",
Expand Down
24 changes: 24 additions & 0 deletions compiler/src/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,30 @@ impl Scope {
}
}

pub fn resolve_direct_method(
&self,
ident: Ident,
class_idx: PoolIndex<Class>,
pool: &ConstantPool,
) -> Result<FunctionCandidates, Cause> {
let mut functions = vec![];

let class = pool.class(class_idx)?;
for fun in &class.functions {
if FunctionSignature::from_raw(&pool.def_name(*fun)?).name() == ident.as_ref() {
functions.push(*fun);
}
}
if functions.is_empty() {
Err(Cause::MethodNotFound(
ident,
Ident::from_heap(pool.def_name(class_idx)?),
))
} else {
Ok(FunctionCandidates { functions })
}
}

pub fn resolve_value(&self, name: Ident) -> Result<Value, Cause> {
self.references
.find(&name)
Expand Down
38 changes: 27 additions & 11 deletions compiler/src/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,12 +793,20 @@ impl<'a> CompilationUnit<'a> {
Symbol::Struct(idx, _) | Symbol::Class(idx, _) => idx,
_ => return Err(Cause::ClassNotFound(class_name.clone()).with_span(ann.span)),
};
let fun_idx = self
let candidates = self
.scope
.resolve_method(name.clone(), target_class_idx, self.pool)
.with_span(ann.span)?
.by_id(&sig, self.pool)
.ok_or_else(|| Cause::MethodNotFound(name, class_name.clone()).with_span(ann.span))?;
.resolve_direct_method(name.clone(), target_class_idx, self.pool)
.ok();
let fun_idx = candidates
.as_ref()
.and_then(|cd| cd.by_id(&sig, self.pool))
.ok_or_else(|| {
if candidates.is_some() {
Cause::NoMethodWithMatchingSignature.with_span(ann.span)
} else {
Cause::NoMethodWithMatchingName.with_span(ann.span)
}
})?;

let wrapped_idx = if let Some(wrapped) = self.wrappers.get(&fun_idx) {
*wrapped
Expand Down Expand Up @@ -840,12 +848,20 @@ impl<'a> CompilationUnit<'a> {
Symbol::Struct(idx, _) | Symbol::Class(idx, _) => idx,
_ => return Err(Cause::ClassNotFound(class_name.clone()).with_span(ann.span)),
};
let fun_idx = self
let candidates = self
.scope
.resolve_method(name.clone(), target_class_idx, self.pool)
.with_span(ann.span)?
.by_id(&sig, self.pool)
.ok_or_else(|| Cause::MethodNotFound(name, class_name.clone()).with_span(ann.span))?;
.resolve_direct_method(name.clone(), target_class_idx, self.pool)
.ok();
let fun_idx = candidates
.as_ref()
.and_then(|cd| cd.by_id(&sig, self.pool))
.ok_or_else(|| {
if candidates.is_some() {
Cause::NoMethodWithMatchingSignature.with_span(ann.span)
} else {
Cause::NoMethodWithMatchingName.with_span(ann.span)
}
})?;
let (parent, base) = (|| {
let def = self.pool.definition(fun_idx).ok()?;
let fun = def.value.as_function()?;
Expand Down Expand Up @@ -895,7 +911,7 @@ impl<'a> CompilationUnit<'a> {

if self
.scope
.resolve_method(name.clone(), target_class_idx, self.pool)
.resolve_direct_method(name.clone(), target_class_idx, self.pool)
.ok()
.and_then(|cd| cd.by_id(&sig, self.pool))
.is_some()
Expand Down

0 comments on commit 19c42a2

Please sign in to comment.