From 4e141379a7fcc40e7b685dc411876746770a4387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Inf=C3=BChr?= Date: Sun, 17 Nov 2024 11:29:34 +0100 Subject: [PATCH] frontend: Use CallArguments for all call kinds --- dora-frontend/src/typeck.rs | 24 +------ dora-frontend/src/typeck/call.rs | 103 +++++++++------------------ dora-frontend/src/typeck/expr.rs | 3 - dora-frontend/src/typeck/function.rs | 68 ------------------ dora-frontend/src/typeck/tests.rs | 17 ++--- 5 files changed, 42 insertions(+), 173 deletions(-) diff --git a/dora-frontend/src/typeck.rs b/dora-frontend/src/typeck.rs index 252be2932..0bd663408 100644 --- a/dora-frontend/src/typeck.rs +++ b/dora-frontend/src/typeck.rs @@ -17,13 +17,12 @@ use crate::typeck::control::{ use crate::typeck::expr::{check_expr, read_ident, read_path, read_path_expr}; pub use crate::typeck::expr::{compute_lit_float, compute_lit_int}; use crate::typeck::function::{ - add_local, arg_allows, args_compatible, args_compatible_fct, check_args_compatible, - check_args_compatible_fct, check_lit_char, check_lit_float, check_lit_int, check_lit_str, - is_simple_enum, TypeCheck, VarManager, + add_local, arg_allows, check_args_compatible, check_args_compatible_fct, check_lit_char, + check_lit_float, check_lit_int, check_lit_str, is_simple_enum, TypeCheck, VarManager, }; use crate::typeck::lookup::find_method_call_candidates; use crate::typeck::stmt::{check_pattern, check_stmt}; -use crate::{ErrorMessage, SourceType, Span}; +use crate::{SourceType, Span}; mod call; mod constck; @@ -193,20 +192,3 @@ pub struct CallArguments { arguments: Vec>, span: Span, } - -impl CallArguments { - fn assume_all_positional(&self, ck: &TypeCheck) -> Vec { - for arg in &self.arguments { - if arg.name.is_some() { - ck.sa - .report(ck.file_id, arg.span, ErrorMessage::UnexpectedNamedArgument); - } - } - - self.arguments - .iter() - .filter(|a| a.name.is_none()) - .map(|p| ck.analysis.ty(p.id)) - .collect::>() - } -} diff --git a/dora-frontend/src/typeck/call.rs b/dora-frontend/src/typeck/call.rs index a82cdcf0f..bc17ad22f 100644 --- a/dora-frontend/src/typeck/call.rs +++ b/dora-frontend/src/typeck/call.rs @@ -11,14 +11,14 @@ use crate::access::{ use crate::interner::Name; use crate::sema::{ find_field_in_class, find_impl, new_identity_type_params, CallType, ClassDefinitionId, - ElementWithFields, EnumDefinitionId, FctDefinitionId, IdentType, Sema, StructDefinitionId, - TraitDefinition, TypeParamId, + ElementWithFields, EnumDefinitionId, FctDefinitionId, IdentType, Param, Sema, + StructDefinitionId, TraitDefinition, TypeParamId, }; use crate::specialize::replace_type; use crate::sym::SymbolKind; use crate::typeck::{ - args_compatible, args_compatible_fct, check_args_compatible_fct, check_expr, - find_method_call_candidates, read_path_expr, CallArguments, TypeCheck, + check_args_compatible, check_args_compatible_fct, check_expr, find_method_call_candidates, + read_path_expr, CallArguments, TypeCheck, }; use crate::typeparamck; use crate::{ @@ -98,7 +98,7 @@ fn check_expr_call_generic_static_method( e: &ast::ExprCallType, tp_id: TypeParamId, name: String, - args: &[SourceType], + arguments: CallArguments, ) -> SourceType { let mut matched_methods = Vec::new(); let interned_name = ck.sa.interner.intern(&name); @@ -124,32 +124,18 @@ fn check_expr_call_generic_static_method( return ty_error(); } - if args.contains(&ty_error()) { - ck.analysis.set_ty(e.id, ty_error()); - return ty_error(); - } - let (trait_method_id, trait_ty) = matched_methods.pop().expect("missing method"); let trait_method = ck.sa.fct(trait_method_id); let tp = SourceType::TypeParam(tp_id); - if !args_compatible_fct( - ck.sa, + check_args_compatible_fct( + ck, trait_method, - args, + arguments, &trait_ty.type_params, Some(tp.clone()), - ) { - let fct_params = trait_method - .params_without_self() - .iter() - .map(|a| ck.ty_name(&a.ty())) - .collect::>(); - let arg_types = args.iter().map(|a| ck.ty_name(a)).collect::>(); - let msg = ErrorMessage::ParamTypesIncompatible(name, fct_params, arg_types); - ck.sa.report(ck.file_id, e.span, msg); - } + ); let call_type = CallType::GenericStaticMethod( tp_id, @@ -182,10 +168,8 @@ fn check_expr_call_expr( return ty_error(); } - let arg_types = arguments.assume_all_positional(ck); - if expr_type.is_lambda() { - return check_expr_call_expr_lambda(ck, e, expr_type, &arg_types); + return check_expr_call_expr_lambda(ck, e, expr_type, arguments); } let trait_id = ck.sa.known.traits.index_get(); @@ -241,7 +225,7 @@ fn check_expr_call_expr_lambda( ck: &mut TypeCheck, e: &ast::ExprCallType, expr_type: SourceType, - arg_types: &[SourceType], + arguments: CallArguments, ) -> SourceType { let (params, return_type) = expr_type.to_lambda().expect("lambda expected"); @@ -249,12 +233,16 @@ fn check_expr_call_expr_lambda( let type_params_count = ck.type_param_definition.type_param_count(); let type_params = new_identity_type_params(type_params_count); - if !args_compatible(ck.sa, params.types(), false, arg_types, &type_params, None) { - let fct_params = params.iter().map(|a| ck.ty_name(&a)).collect::>(); - let arg_types = arg_types.iter().map(|a| ck.ty_name(a)).collect::>(); - let msg = ErrorMessage::LambdaParamTypesIncompatible(fct_params, arg_types); - ck.sa.report(ck.file_id, e.span, msg); - } + let regular_params = params.iter().map(|p| Param::new_ty(p)).collect::>(); + + check_args_compatible( + ck, + regular_params.as_slice(), + None, + arguments, + &type_params, + None, + ); let call_type = CallType::Lambda(params, return_type.clone()); @@ -374,8 +362,6 @@ fn check_expr_call_method( fct_type_params: SourceTypeArray, arguments: CallArguments, ) -> SourceType { - let arg_types = arguments.assume_all_positional(ck); - if let SourceType::TypeParam(id) = object_type { assert_eq!(fct_type_params.len(), 0); return check_expr_call_generic_type_param( @@ -384,11 +370,11 @@ fn check_expr_call_method( SourceType::TypeParam(id), id, method_name, - &arg_types, + arguments, ); } else if object_type.is_self() { assert_eq!(fct_type_params.len(), 0); - return check_expr_call_self(ck, e, method_name, &arg_types); + return check_expr_call_self(ck, e, method_name, arguments); } if object_type.is_error() { @@ -826,7 +812,7 @@ fn check_expr_call_self( ck: &mut TypeCheck, e: &ast::ExprCallType, name: String, - args: &[SourceType], + arguments: CallArguments, ) -> SourceType { let mut matched_methods = Vec::new(); let interned_name = ck.sa.interner.intern(&name); @@ -865,23 +851,13 @@ fn check_expr_call_self( CallType::Method(SourceType::This, trait_method_id, trait_type_params.clone()); ck.analysis.map_calls.insert(e.id, Arc::new(call_type)); - if !args_compatible_fct( - ck.sa, + check_args_compatible_fct( + ck, trait_method, - args, + arguments, &trait_type_params, Some(SourceType::This), - ) { - let trait_params = trait_method - .params_without_self() - .iter() - .map(|a| specialize_type(ck.sa, a.ty(), &trait_type_params)) - .map(|a| ck.ty_name(&a)) - .collect::>(); - let param_names = args.iter().map(|a| ck.ty_name(a)).collect::>(); - let msg = ErrorMessage::ParamTypesIncompatible(name, trait_params, param_names); - ck.sa.report(ck.file_id, e.span, msg); - } + ); return_type } else { @@ -921,7 +897,7 @@ fn check_expr_call_generic_type_param( object_type: SourceType, id: TypeParamId, name: String, - args: &[SourceType], + arguments: CallArguments, ) -> SourceType { assert!(object_type.is_type_param()); let mut matched_methods = Vec::new(); @@ -962,23 +938,13 @@ fn check_expr_call_generic_type_param( ); ck.analysis.map_calls.insert(e.id, Arc::new(call_type)); - if !args_compatible_fct( - ck.sa, + check_args_compatible_fct( + ck, trait_method, - args, + arguments, &trait_type_params, Some(object_type.clone()), - ) { - let trait_params = trait_method - .params_without_self() - .iter() - .map(|a| specialize_type(ck.sa, a.ty(), &trait_type_params)) - .map(|a| ck.ty_name(&a)) - .collect::>(); - let param_names = args.iter().map(|a| ck.ty_name(a)).collect::>(); - let msg = ErrorMessage::ParamTypesIncompatible(name, trait_params, param_names); - ck.sa.report(ck.file_id, e.span, msg); - } + ); return_type } else { @@ -1144,8 +1110,7 @@ fn check_expr_call_path( ck.sa.report(ck.file_id, callee_as_path.lhs.span(), msg); } - let arg_types = arguments.assume_all_positional(ck); - check_expr_call_generic_static_method(ck, e, id, method_name, &arg_types) + check_expr_call_generic_static_method(ck, e, id, method_name, arguments) } Some(SymbolKind::Module(module_id)) => { diff --git a/dora-frontend/src/typeck/expr.rs b/dora-frontend/src/typeck/expr.rs index 60d11b9f2..46a722900 100644 --- a/dora-frontend/src/typeck/expr.rs +++ b/dora-frontend/src/typeck/expr.rs @@ -280,9 +280,6 @@ fn check_expr_assign_call(ck: &mut TypeCheck, e: &ast::ExprBinType) { let value_type = check_expr(ck, &e.rhs, SourceType::Any); ck.analysis.set_ty(e.rhs.id(), value_type.clone()); - let mut arg_types = args.assume_all_positional(ck); - arg_types.push(value_type.clone()); - let trait_id = ck.sa.known.traits.index_set(); let trait_ty = TraitType::from_trait_id(trait_id); diff --git a/dora-frontend/src/typeck/function.rs b/dora-frontend/src/typeck/function.rs index 9357ce18b..34145357b 100644 --- a/dora-frontend/src/typeck/function.rs +++ b/dora-frontend/src/typeck/function.rs @@ -425,25 +425,6 @@ pub(super) fn add_local( } } -pub(super) fn args_compatible_fct( - sa: &Sema, - callee: &FctDefinition, - args: &[SourceType], - type_params: &SourceTypeArray, - self_ty: Option, -) -> bool { - let arg_types = callee.params_without_self(); - let variadic_arguments = callee.params.is_variadic(); - args_compatible( - sa, - &arg_types.iter().map(|p| p.ty()).collect::>(), - variadic_arguments, - args, - type_params, - self_ty, - ) -} - pub(super) fn check_args_compatible_fct( ck: &TypeCheck, callee: &FctDefinition, @@ -537,55 +518,6 @@ pub(super) fn check_args_compatible( } } -pub(super) fn args_compatible( - sa: &Sema, - fct_arg_types: &[SourceType], - variadic_arguments: bool, - args: &[SourceType], - type_params: &SourceTypeArray, - self_ty: Option, -) -> bool { - let right_number_of_arguments = if variadic_arguments { - fct_arg_types.len() - 1 <= args.len() - } else { - fct_arg_types.len() == args.len() - }; - - if !right_number_of_arguments { - return false; - } - - let (def, rest_ty): (&[SourceType], Option) = if variadic_arguments { - ( - &fct_arg_types[0..fct_arg_types.len() - 1], - fct_arg_types.last().cloned(), - ) - } else { - (&fct_arg_types, None) - }; - - for (ind, def_arg) in def.iter().enumerate() { - let def_arg = replace_type(sa, def_arg.clone(), Some(&type_params), self_ty.clone()); - - if !arg_allows(sa, def_arg, args[ind].clone(), self_ty.clone()) { - return false; - } - } - - if let Some(rest_ty) = rest_ty { - let ind = def.len(); - let rest_ty = replace_type(sa, rest_ty, Some(&type_params), self_ty.clone()); - - for expr_ty in &args[ind..] { - if !arg_allows(sa, rest_ty.clone(), expr_ty.clone(), self_ty.clone()) { - return false; - } - } - } - - true -} - pub(super) fn arg_allows( sa: &Sema, def: SourceType, diff --git a/dora-frontend/src/typeck/tests.rs b/dora-frontend/src/typeck/tests.rs index dc1c67cdc..2392b1bbc 100644 --- a/dora-frontend/src/typeck/tests.rs +++ b/dora-frontend/src/typeck/tests.rs @@ -1505,8 +1505,8 @@ fn test_static_method_call_with_type_param() { err( "trait X { static fn foo(): Int32; } fn f[T: X](): Int32 { return T::foo(1i32); }", - (2, 38), - ErrorMessage::ParamTypesIncompatible("foo".into(), Vec::new(), vec!["Int32".into()]), + (2, 45), + ErrorMessage::SuperfluousArgument, ); ok("trait X { static fn foo(): Int32; } @@ -3596,10 +3596,7 @@ fn basic_lambda() { foo(1i32) }", (2, 9), - ErrorMessage::LambdaParamTypesIncompatible( - vec!["Int32".into(), "Int32".into()], - vec!["Int32".into()], - ), + ErrorMessage::MissingArguments(2, 1), ); } @@ -3915,12 +3912,8 @@ fn test_generic_trait_method_call() { t.foo(1, 2); } ", - (4, 13), - ErrorMessage::ParamTypesIncompatible( - "foo".into(), - vec!["Int64".into()], - vec!["Int64".into(), "Int64".into()], - ), + (4, 22), + ErrorMessage::SuperfluousArgument, ); }