Skip to content

Commit

Permalink
feat: report diagnostic errors if trait or methods do not exist (#36)
Browse files Browse the repository at this point in the history
This replaces a todo ice!() in the callable reference inference code.
  • Loading branch information
junlarsen authored Feb 4, 2025
1 parent d95f756 commit 722d1e1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 18 deletions.
11 changes: 11 additions & 0 deletions compiler/eight-diagnostics/src/errors/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ declare_error_type! {
UnknownIntrinsicType(UnknownIntrinsicTypeError),
TraitInstanceMissingFn(TraitInstanceMissingFnError),
TraitDoesNotExist(TraitDoesNotExistError),
TraitMethodDoesNotExist(TraitMethodDoesNotExistError),
TraitMissingInstance(TraitMissingInstanceError),
WrongTraitTypeArgumentCount(WrongTraitTypeArgumentCount),
TypeParameterShadowsExisting(TypeParameterShadowsExisting),
Expand Down Expand Up @@ -188,6 +189,16 @@ pub struct TraitDoesNotExistError {
pub span: Span,
}

#[derive(Error, Diagnostic, Debug, PartialEq)]
#[diagnostic(code(sema::trait_method_does_not_exist))]
#[error("trait {trait_name} does not have method {method_name}")]
pub struct TraitMethodDoesNotExistError {
pub trait_name: String,
pub method_name: String,
#[label = "required method {method_name} for trait {trait_name}"]
pub span: Span,
}

#[derive(Error, Diagnostic, Debug)]
#[diagnostic(code(sema::trait_missing_instance))]
#[error("trait {name} does not have instance {instance_name}")]
Expand Down
36 changes: 18 additions & 18 deletions compiler/eight-middle/src/hir_type_check_pass/typing_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ use eight_diagnostics::errors::hir::{
DereferenceOfNonPointerError, FunctionTypeMismatchError, HirError,
InvalidFieldReferenceOfNonStructError, InvalidStructFieldReferenceError, MissingFieldError,
SelfReferentialTypeError, TraitDoesNotExistError, TraitInstanceMissingFnError,
TraitMissingInstanceError, TypeMismatchError, TypeParameterShadowsExisting, UnknownFieldError,
WrongFunctionTypeArgumentCount,
TraitMethodDoesNotExistError, TraitMissingInstanceError, TypeMismatchError,
TypeParameterShadowsExisting, UnknownFieldError, WrongFunctionTypeArgumentCount,
};
use eight_diagnostics::ice;
use eight_span::Span;
Expand Down Expand Up @@ -332,15 +332,20 @@ impl<'hir> TypingContext<'hir> {
let HirCallableSymbol::TraitFunction(sym) = &mut expr.symbol else {
ice!("called infer_trait_function_callable_reference_expr() on non-trait function symbol reference");
};
let Some((trait_signature, method_signature)) = self
.signature
.query_trait_and_signature_by_name(sym.trait_name, sym.method_name)
else {
ice!(
"called infer() on '{}::{}' that doesn't exist in the context",
sym.trait_name,
sym.method_name
);
let Some(trait_signature) = self.signature.query_trait_by_name(sym.trait_name) else {
return Err(HirError::TraitDoesNotExist(TraitDoesNotExistError {
name: sym.trait_name.to_owned(),
span: sym.trait_name_span,
}));
};
let Some(method_signature) = trait_signature.methods.get(sym.method_name) else {
return Err(HirError::TraitMethodDoesNotExist(
TraitMethodDoesNotExistError {
trait_name: sym.trait_name.to_owned(),
method_name: sym.method_name.to_owned(),
span: sym.method_name_span,
},
));
};
// Instantiate all the generic types present on both the trait and the method.
let mut instantiations = HashMap::new();
Expand Down Expand Up @@ -924,12 +929,6 @@ impl<'hir> TypingContext<'hir> {
/// An instance constraint requires that there exists an instance of trait `name` that for the
/// given types `type_arguments`.
pub fn unify_instance(&mut self, constraint: InstanceConstraint<'hir>) -> HirResult<()> {
self.signature
.query_trait_by_name(constraint.name)
.ok_or(HirError::TraitDoesNotExist(TraitDoesNotExistError {
name: constraint.name.to_owned(),
span: constraint.name_span,
}))?;
let substitutions = constraint
.type_arguments
.iter()
Expand Down Expand Up @@ -976,7 +975,8 @@ impl<'hir> TypingContext<'hir> {
constraint.trait_name,
trait_substitutions.as_slice(),
)
.unwrap_or_else(|| ice!("trait instance not found"));
// TODO: This should emit an error
.unwrap_or_else(|| ice!("no suitable trait instance not found"));
let method = instance.methods.get(&constraint.method_name).ok_or(
HirError::TraitInstanceMissingFn(TraitInstanceMissingFnError {
name: constraint.trait_name.to_owned(),
Expand Down

0 comments on commit 722d1e1

Please sign in to comment.