diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs index b4c9bb5d7a4..94906a2d9c7 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/method_application.rs @@ -1,11 +1,11 @@ use crate::{ decl_engine::{ - engine::DeclEngineReplace, DeclEngineInsert, DeclRefFunction, ReplaceDecls, - UpdateConstantExpression, + engine::{DeclEngineGet, DeclEngineReplace}, + DeclEngineInsert, DeclRefFunction, ReplaceDecls, UpdateConstantExpression, }, language::{ parsed::*, - ty::{self}, + ty::{self, TyDecl}, *, }, namespace::TryInsertingTraitImplOnFailure, @@ -552,10 +552,14 @@ pub(crate) fn monomorphize_method_application( ref call_path, ref mut arguments, ref mut type_binding, + call_path_typeid, .. } = expr { let decl_engine = ctx.engines.de(); + let type_engine = ctx.engines.te(); + let engines = ctx.engines(); + *fn_ref = monomorphize_method( handler, ctx.by_ref(), @@ -568,6 +572,41 @@ pub(crate) fn monomorphize_method_application( *arguments = unify_arguments_and_parameters(handler, ctx.by_ref(), arguments, &method.parameters)?; + // unify method return type with current ctx.type_annotation(). + handler.scope(|handler| { + type_engine.unify( + handler, + engines, + method.return_type.type_id, + ctx.type_annotation(), + &method.return_type.span(), + "Function return type does not match up with local type annotation.", + None, + ); + Ok(()) + })?; + + // This handles the case of substituting the generic blanket type by call_path_typeid. + if let Some(TyDecl::ImplTrait(t)) = method.clone().implementing_type { + let t = engines.de().get(&t.decl_id).implementing_for; + if let TypeInfo::Custom { + qualified_call_path, + type_arguments: _, + root_type_id: _, + } = type_engine.get(t.initial_type_id) + { + for p in method.type_parameters.clone() { + if p.name_ident.as_str() == qualified_call_path.call_path.suffix.as_str() { + let type_subst = TypeSubstMap::from_type_parameters_and_type_arguments( + vec![t.initial_type_id], + vec![call_path_typeid.unwrap()], + ); + method.subst(&type_subst, engines); + } + } + } + } + // Handle the trait constraints. This includes checking to see if the trait // constraints are satisfied and replacing old decl ids based on the // constraint with new decl ids based on the new type. diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_trait_constraints/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_trait_constraints/src/main.sw index a0efb458480..42b0e26cfa7 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_trait_constraints/src/main.sw +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_trait_constraints/src/main.sw @@ -56,8 +56,7 @@ fn main() -> bool { assert_eq(s2.data_a.my_add(1,2),3); assert_eq(s2.data_b.my_add(1,2),3); - // TODO Uncomment this after #5208 is fixed - //let _i: Struct3 = 1_u64.into(); + let _i: Struct3 = 1_u64.into(); true } \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_trait_constraints/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_trait_constraints/test.toml index f9ad984775d..321bcb15b5f 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_trait_constraints/test.toml +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/generic_trait_constraints/test.toml @@ -1,4 +1,4 @@ category = "run" expected_result = { action = "return", value = 1 } validate_abi = false -expected_warnings = 3 \ No newline at end of file +expected_warnings = 1 \ No newline at end of file