Skip to content

Commit

Permalink
frontend: Clean up MethodLookup a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
dinfuehr committed Nov 12, 2024
1 parent 4b333cd commit e62d456
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 73 deletions.
26 changes: 10 additions & 16 deletions dora-frontend/src/error/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ pub enum ErrorMessage {
UnknownStruct(String),
UnknownFunction(String),
UnknownField(String, String),
UnknownMethod(String, String, Vec<String>),
UnknownMethod(String, String),
UnknownEnumVariant(String),
UnknownSuffix,
MultipleCandidatesForMethod(String, String, Vec<String>),
MultipleCandidatesForMethod(String, String),
VariadicParameterNeedsToBeLast,
UnknownMethodForTypeParam,
MultipleCandidatesForTypeParam,
MultipleCandidatesForStaticMethodWithTypeParam,
UnknownStaticMethodWithTypeParam,
UnknownStaticMethod(String, String, Vec<String>),
UnknownStaticMethod(String, String),
UnknownCtor,
AliasExists(String, Span),
TypeExists(String, Span),
Expand Down Expand Up @@ -223,22 +223,17 @@ impl ErrorMessage {
ErrorMessage::UnknownIdentifier(ref name) => format!("unknown identifier `{}`.", name),
ErrorMessage::UnknownStruct(ref name) => format!("unknown struct `{}`.", name),
ErrorMessage::UnknownFunction(ref name) => format!("unknown function `{}`", name),
ErrorMessage::UnknownMethod(ref cls, ref name, ref args) => {
let args = args.join(", ");
format!(
"no method with definition `{}({})` in type `{}`.",
name, args, cls
)
ErrorMessage::UnknownMethod(ref cls, ref name) => {
format!("no method with name `{}` in type `{}`.", name, cls)
}
ErrorMessage::UnknownEnumVariant(ref name) => {
format!("no variant with name `{}` in enumeration.", name)
}
ErrorMessage::UnknownSuffix => "unknown integer suffix".into(),
ErrorMessage::MultipleCandidatesForMethod(ref cls, ref name, ref args) => {
let args = args.join(", ");
ErrorMessage::MultipleCandidatesForMethod(ref cls, ref name) => {
format!(
"multiple candidates for definition `{}({})` in class `{}`.",
name, args, cls
"multiple candidates for method named `{}` in type `{}`.",
name, cls
)
}
ErrorMessage::VariadicParameterNeedsToBeLast => {
Expand All @@ -256,9 +251,8 @@ impl ErrorMessage {
ErrorMessage::UnknownStaticMethodWithTypeParam => {
"no static method with this name found for type param.".into()
}
ErrorMessage::UnknownStaticMethod(ref cls, ref name, ref args) => {
let args = args.join(", ");
format!("no static method `{}::{}({})`.", cls, name, args)
ErrorMessage::UnknownStaticMethod(ref cls, ref name) => {
format!("no static method of name `{}` for type `{}`.", name, cls,)
}
ErrorMessage::UnexpectedTypeAliasAssignment => "no type expected.".into(),
ErrorMessage::UnknownCtor => "class does not have constructor.".into(),
Expand Down
4 changes: 2 additions & 2 deletions dora-frontend/src/impldefck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1074,7 +1074,7 @@ mod tests {
}
",
(9, 13),
ErrorMessage::UnknownMethod("(Int64, String) -> Int64".into(), "foo".into(), vec![]),
ErrorMessage::UnknownMethod("(Int64, String) -> Int64".into(), "foo".into()),
);

err(
Expand All @@ -1090,7 +1090,7 @@ mod tests {
}
",
(9, 13),
ErrorMessage::UnknownMethod("(Int64, Int64) -> Bool".into(), "foo".into(), vec![]),
ErrorMessage::UnknownMethod("(Int64, Int64) -> Bool".into(), "foo".into()),
);
}

Expand Down
2 changes: 1 addition & 1 deletion dora-frontend/src/traitdefck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod tests {
err(
"trait Foo { fn foo() { self.bar(); } }",
(1, 24),
ErrorMessage::UnknownMethod("Self".into(), "bar".into(), Vec::new()),
ErrorMessage::UnknownMethod("Self".into(), "bar".into()),
);

err(
Expand Down
4 changes: 4 additions & 0 deletions dora-frontend/src/typeck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,4 +213,8 @@ impl CallArguments {
.map(|p| ck.analysis.ty(p.id))
.collect::<Vec<SourceType>>()
}

fn len(&self) -> usize {
self.arguments.len()
}
}
10 changes: 4 additions & 6 deletions dora-frontend/src/typeck/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,11 +876,10 @@ fn check_expr_call_self(

return_type
} else {
let param_names = args.iter().map(|a| ck.ty_name(a)).collect::<Vec<String>>();
let msg = if matched_methods.is_empty() {
ErrorMessage::UnknownMethod("Self".into(), name, param_names)
ErrorMessage::UnknownMethod("Self".into(), name)
} else {
ErrorMessage::MultipleCandidatesForMethod("Self".into(), name, param_names)
ErrorMessage::MultipleCandidatesForMethod("Self".into(), name)
};

ck.sa.report(ck.file_id, e.span, msg);
Expand Down Expand Up @@ -1249,11 +1248,10 @@ pub(super) fn find_method(
if descriptor.is_none() {
let type_name = ck.ty_name(&object_type);
let name = ck.sa.interner.str(name).to_string();
let param_names = args.iter().map(|a| ck.ty_name(a)).collect::<Vec<String>>();
let msg = if is_static {
ErrorMessage::UnknownStaticMethod(type_name, name, param_names)
ErrorMessage::UnknownStaticMethod(type_name, name)
} else {
ErrorMessage::UnknownMethod(type_name, name, param_names)
ErrorMessage::UnknownMethod(type_name, name)
};

ck.sa.report(ck.file_id, span, msg);
Expand Down
82 changes: 81 additions & 1 deletion dora-frontend/src/typeck/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::sema::{
PackageDefinitionId, Param, ScopeId, Sema, SourceFileId, TypeParamDefinition, Var, VarAccess,
VarId, VarLocation, Visibility,
};
use crate::typeck::{check_expr, check_stmt};
use crate::typeck::{check_expr, check_stmt, CallArguments};
use crate::{
always_returns, expr_always_returns, replace_type, report_sym_shadow_span, ModuleSymTable,
SourceType, SourceTypeArray, SymbolKind,
Expand Down Expand Up @@ -444,6 +444,26 @@ pub(super) fn args_compatible_fct(
)
}

#[allow(unused)]
pub(super) fn args_compatible_fct2(
ck: &TypeCheck,
callee: &FctDefinition,
args: CallArguments,
type_params: &SourceTypeArray,
self_ty: Option<SourceType>,
) -> bool {
let arg_types = callee.params_without_self();
let variadic_arguments = callee.is_variadic.get();
args_compatible2(
ck,
arg_types,
variadic_arguments,
&args,
type_params,
self_ty,
)
}

pub(super) fn args_compatible(
sa: &Sema,
fct_arg_types: &[SourceType],
Expand Down Expand Up @@ -493,6 +513,66 @@ pub(super) fn args_compatible(
true
}

pub(super) fn args_compatible2(
ck: &TypeCheck,
fct_params: &[Param],
is_variadic: bool,
args: &CallArguments,
type_params: &SourceTypeArray,
self_ty: Option<SourceType>,
) -> bool {
let right_number_of_arguments = if is_variadic {
fct_params.len() - 1 <= args.len()
} else {
fct_params.len() == args.len()
};

if !right_number_of_arguments {
return false;
}

let (fixed_params, variadic_param): (&[Param], Option<&Param>) = if is_variadic {
(&fct_params[0..fct_params.len() - 1], fct_params.last())
} else {
(&fct_params, None)
};

for (ind, param) in fixed_params.iter().enumerate() {
let param_ty = replace_type(
ck.sa,
param.ty().clone(),
Some(&type_params),
self_ty.clone(),
);
let arg = &args.arguments[ind];
let arg_ty = ck.analysis.ty(arg.id);

if !arg_allows(ck.sa, param_ty, arg_ty, self_ty.clone()) {
return false;
}
}

if let Some(variadic_param) = variadic_param {
let ind = fixed_params.len();
let variadic_ty = replace_type(
ck.sa,
variadic_param.ty(),
Some(&type_params),
self_ty.clone(),
);

for arg in &args.arguments[ind..] {
let arg_ty = ck.analysis.ty(arg.id);

if !arg_allows(ck.sa, variadic_ty.clone(), arg_ty, self_ty.clone()) {
return false;
}
}
}

true
}

fn arg_allows(sa: &Sema, def: SourceType, arg: SourceType, self_ty: Option<SourceType>) -> bool {
match def {
SourceType::Error => true,
Expand Down
14 changes: 5 additions & 9 deletions dora-frontend/src/typeck/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ impl<'a> MethodLookup<'a> {

pub fn find(&mut self) -> MethodLookupResult {
let kind = self.kind.clone().expect("kind not set");
let args = self.args.expect("args not set");
let mut result = MethodLookupResult::new();

let fct_id = match kind {
Expand All @@ -164,28 +163,23 @@ impl<'a> MethodLookup<'a> {
fct_id
} else if self.report_errors {
let name = self.name.expect("name not set");

let name = self.sa.interner.str(name).to_string();
let param_names = args
.iter()
.map(|a| self.ty_name(a))
.collect::<Vec<String>>();

let msg = match kind {
LookupKind::Callee(_) => unreachable!(),
LookupKind::Method(ref obj) => {
let type_name = self.ty_name(obj);

if result.found_multiple_functions {
ErrorMessage::MultipleCandidatesForMethod(type_name, name, param_names)
ErrorMessage::MultipleCandidatesForMethod(type_name, name)
} else {
ErrorMessage::UnknownMethod(type_name, name, param_names)
ErrorMessage::UnknownMethod(type_name, name)
}
}

LookupKind::Static(ref obj) => {
let type_name = self.ty_name(obj);
ErrorMessage::UnknownStaticMethod(type_name, name, param_names)
ErrorMessage::UnknownStaticMethod(type_name, name)
}
};

Expand Down Expand Up @@ -216,6 +210,8 @@ impl<'a> MethodLookup<'a> {
return result;
}

let args = self.args.expect("args not set");

if args.contains(&ty::error()) {
return result;
}
Expand Down
Loading

0 comments on commit e62d456

Please sign in to comment.