Skip to content

Commit 5e22d64

Browse files
tritaoIGI-111
andauthored
Improve method resolution for trait method name bindings (#7364)
## Description This PR improves method resolution for trait method name bindings, like this following example: ```sway script; use std::time::Time; pub fn main() { let duration = Time::now().duration_since(Time::from(0)).unwrap(); let _ = duration + duration; } ``` This fix is implemented in [Gather trait impls from the argument type module when handling trait operator calls.](8610000). A general refactor was also done for associated method resolution functions: [Refactor TypeCheckContext::find_method_for_type.](ace60ce) [Refactor resolve_method_name.](9d97d46) Closes #7330. ## Checklist - [x] I have linked to any relevant issues. - [x] I have commented my code, particularly in hard-to-understand areas. - [x] I have updated the documentation where relevant (API docs, the reference, and the Sway book). - [ ] If my change requires substantial documentation changes, I have [requested support from the DevRel team](https://github.com/FuelLabs/devrel-requests/issues/new/choose) - [x] I have added tests that prove my fix is effective or that my feature works. - [x] I have added (or requested a maintainer to add) the necessary `Breaking*` or `New Feature` labels where relevant. - [x] I have done my best to ensure that my PR adheres to [the Fuel Labs Code Review Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md). - [x] I have requested a review from the relevant team or maintainers. --------- Co-authored-by: IGI-111 <igi-111@protonmail.com>
1 parent 4f1af43 commit 5e22d64

File tree

8 files changed

+614
-416
lines changed

8 files changed

+614
-416
lines changed

sway-core/src/language/call_path.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,13 @@ impl CallPath {
375375
.collect::<Vec<_>>()
376376
}
377377

378+
pub fn as_vec_ident(&self) -> Vec<Ident> {
379+
self.as_vec_string()
380+
.iter()
381+
.map(|s| Ident::new_no_span(s.clone()))
382+
.collect::<Vec<_>>()
383+
}
384+
378385
/// Create a full [CallPath] from a given [Ident] and the [Namespace] in which the [Ident] is
379386
/// declared.
380387
///

sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs

Lines changed: 42 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -900,65 +900,58 @@ fn unify_arguments_and_parameters(
900900
pub(crate) fn resolve_method_name(
901901
handler: &Handler,
902902
mut ctx: TypeCheckContext,
903-
method_name: &TypeBinding<MethodName>,
903+
method_name_binding: &TypeBinding<MethodName>,
904904
arguments_types: &[TypeId],
905905
) -> Result<(DeclRefFunction, TypeId), ErrorEmitted> {
906906
ctx.engines
907907
.obs()
908-
.raise_on_before_method_resolution(&ctx, method_name, arguments_types);
908+
.raise_on_before_method_resolution(&ctx, method_name_binding, arguments_types);
909909

910910
let type_engine = ctx.engines.te();
911911
let engines = ctx.engines();
912912

913-
// retrieve the function declaration using the components of the method name
914-
let (decl_ref, type_id) = match &method_name.inner {
913+
// Helper: first argument type or an unknown placeholder.
914+
let first_arg_or_unknown = || {
915+
arguments_types
916+
.first()
917+
.cloned()
918+
.unwrap_or_else(|| type_engine.new_unknown())
919+
};
920+
921+
let (type_id, module_path, method_ident) = match &method_name_binding.inner {
915922
MethodName::FromType {
916923
call_path_binding,
917924
method_name,
918925
} => {
919-
// type check the call path
920926
let type_id = call_path_binding
921927
.type_check_with_type_info(handler, &mut ctx)
922928
.unwrap_or_else(|err| type_engine.id_of_error_recovery(err));
923929

924-
// find the module that the symbol is in
925-
let type_info_prefix = &call_path_binding
930+
let type_info_path = call_path_binding
926931
.inner
927-
.to_fullpath(engines, ctx.namespace())
928-
.prefixes;
932+
.to_fullpath(engines, ctx.namespace());
933+
let module_path = type_info_path.prefixes.clone();
929934
ctx.namespace()
930-
.require_module_from_absolute_path(handler, type_info_prefix)?;
935+
.require_module_from_absolute_path(handler, &module_path)?;
931936

932-
// find the method
933-
let decl_ref = ctx.find_method_for_type(
934-
handler,
935-
type_id,
936-
type_info_prefix,
937-
method_name,
938-
ctx.type_annotation(),
939-
arguments_types,
940-
None,
941-
)?;
942-
943-
(decl_ref, type_id)
937+
(type_id, module_path, method_name)
944938
}
939+
945940
MethodName::FromTrait { call_path } => {
946-
// find the module that the symbol is in
947-
let module_path = match call_path.callpath_type {
941+
let module_path: Vec<_> = match call_path.callpath_type {
948942
CallPathType::RelativeToPackageRoot => {
949943
let mut path = vec![ctx.namespace().current_package_name().clone()];
950-
for ident in call_path.prefixes.iter() {
951-
path.push(ident.clone())
952-
}
944+
path.extend(call_path.prefixes.iter().cloned());
953945
path
954946
}
955947
CallPathType::Full => call_path.prefixes.clone(),
956948
CallPathType::Ambiguous => {
949+
let first = call_path.prefixes.first().expect("prefixes is non-empty");
957950
if ctx
958951
.namespace()
959952
.current_module()
960953
.submodules()
961-
.contains_key(call_path.prefixes.first().unwrap().as_str())
954+
.contains_key(first.as_str())
962955
{
963956
ctx.namespace().prepend_module_path(&call_path.prefixes)
964957
} else {
@@ -967,77 +960,38 @@ pub(crate) fn resolve_method_name(
967960
}
968961
};
969962

970-
// find the type of the first argument
971-
let type_id = arguments_types
972-
.first()
973-
.cloned()
974-
.unwrap_or_else(|| type_engine.new_unknown());
975-
976-
// find the method
977-
let decl_ref = ctx.find_method_for_type(
978-
handler,
979-
type_id,
980-
&module_path,
981-
&call_path.suffix,
982-
ctx.type_annotation(),
983-
arguments_types,
984-
None,
985-
)?;
986-
987-
(decl_ref, type_id)
963+
let type_id = first_arg_or_unknown();
964+
(type_id, module_path, &call_path.suffix)
988965
}
989-
MethodName::FromModule { method_name } => {
990-
// find the module that the symbol is in
991-
let module_path = ctx.namespace().current_mod_path();
992966

993-
// find the type of the first argument
994-
let type_id = arguments_types
995-
.first()
996-
.cloned()
997-
.unwrap_or_else(|| type_engine.new_unknown());
998-
999-
// find the method
1000-
let decl_ref = ctx.find_method_for_type(
1001-
handler,
1002-
type_id,
1003-
module_path.as_slice(),
1004-
method_name,
1005-
ctx.type_annotation(),
1006-
arguments_types,
1007-
None,
1008-
)?;
1009-
1010-
(decl_ref, type_id)
967+
MethodName::FromModule { method_name } => {
968+
let module_path = ctx.namespace().current_mod_path().to_vec();
969+
let type_id = first_arg_or_unknown();
970+
(type_id, module_path, method_name)
1011971
}
972+
1012973
MethodName::FromQualifiedPathRoot {
1013-
ty,
1014-
as_trait,
1015-
method_name,
974+
ty, method_name, ..
1016975
} => {
1017-
// type check the call path
1018976
let type_id = ty.type_id();
1019-
1020-
// find the module that the symbol is in
1021-
let module_path = ctx.namespace().current_mod_path();
1022-
1023-
// find the method
1024-
let decl_ref = ctx.find_method_for_type(
1025-
handler,
1026-
type_id,
1027-
module_path,
1028-
method_name,
1029-
ctx.type_annotation(),
1030-
arguments_types,
1031-
Some(*as_trait),
1032-
)?;
1033-
1034-
(decl_ref, type_id)
977+
let module_path = ctx.namespace().current_mod_path().to_vec();
978+
(type_id, module_path, method_name)
1035979
}
1036980
};
1037981

982+
let decl_ref = ctx.find_method_for_type(
983+
handler,
984+
type_id,
985+
module_path.as_slice(),
986+
method_ident,
987+
ctx.type_annotation(),
988+
arguments_types,
989+
Some(&method_name_binding.inner),
990+
)?;
991+
1038992
ctx.engines.obs().raise_on_after_method_resolution(
1039993
&ctx,
1040-
method_name,
994+
method_name_binding,
1041995
arguments_types,
1042996
decl_ref.clone(),
1043997
type_id,

0 commit comments

Comments
 (0)