From da7c77128658f8d2fb3c201fb9a4d17645ec9ad4 Mon Sep 17 00:00:00 2001 From: Marcos Henrich Date: Mon, 2 Sep 2024 14:18:56 +0100 Subject: [PATCH] Fixes mismatched types in ABI cast. ABI cast generates TypeInfo::ContractCaller which contains an address that is an expression. While doing the first and second code block passes we would obtain different expressions because of first passes optimizations. This PR disables first pass optimizations while type checking address expression so there isn't any mismatched types. --- .../semantic_analysis/ast_node/code_block.rs | 1 + .../ast_node/declaration/configurable.rs | 2 +- .../ast_node/declaration/constant.rs | 2 +- .../ast_node/declaration/declaration.rs | 2 +- .../ast_node/declaration/impl_trait.rs | 28 +++++------ .../ast_node/declaration/trait.rs | 14 +++--- .../ast_node/expression/typed_expression.rs | 6 ++- .../typed_expression/function_application.rs | 4 +- .../typed_expression/method_application.rs | 6 +-- .../src/semantic_analysis/namespace/mod.rs | 2 +- .../src/semantic_analysis/namespace/root.rs | 2 +- .../semantic_analysis/namespace/trait_map.rs | 50 ++++++++----------- .../semantic_analysis/type_check_context.rs | 36 +++++++++---- .../ast_elements/type_parameter.rs | 6 +-- sway-core/src/type_system/id.rs | 2 +- .../Forc.lock | 13 +++++ .../Forc.toml | 9 ++++ .../src/main.sw | 18 +++++++ .../test.toml | 5 ++ 19 files changed, 135 insertions(+), 73 deletions(-) create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/Forc.lock create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/Forc.toml create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/src/main.sw create mode 100644 test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/test.toml diff --git a/sway-core/src/semantic_analysis/ast_node/code_block.rs b/sway-core/src/semantic_analysis/ast_node/code_block.rs index e063566d6f8..731a02457bb 100644 --- a/sway-core/src/semantic_analysis/ast_node/code_block.rs +++ b/sway-core/src/semantic_analysis/ast_node/code_block.rs @@ -56,6 +56,7 @@ impl ty::TyCodeBlock { // This is required to fix the test case numeric_type_propagation and issue #6371 ctx.by_ref() .with_collecting_unifications() + .with_code_block_first_pass(true) .scoped(|mut ctx| { code_block.contents.iter().for_each(|node| { ty::TyAstNode::type_check(&Handler::default(), ctx.by_ref(), node).ok(); diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/configurable.rs b/sway-core/src/semantic_analysis/ast_node/declaration/configurable.rs index a1c2f485af5..7619d1d2f02 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/configurable.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/configurable.rs @@ -50,7 +50,7 @@ impl ty::TyConfigurableDecl { // this subst is required to replace associated types, namely TypeInfo::TraitType. type_ascription.type_id.subst( &ctx.type_subst(), - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); if !is_screaming_snake_case(name.as_str()) { diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/constant.rs b/sway-core/src/semantic_analysis/ast_node/declaration/constant.rs index d911b9b99e3..4a9f903b282 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/constant.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/constant.rs @@ -45,7 +45,7 @@ impl ty::TyConstantDecl { // this subst is required to replace associated types, namely TypeInfo::TraitType. type_ascription.type_id.subst( &ctx.type_subst(), - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); if !is_screaming_snake_case(name.as_str()) { diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs index 817a997a9ba..49a2b6a636e 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/declaration.rs @@ -162,7 +162,7 @@ impl TyDecl { }, }; - if !ctx.collecting_unifications() { + if !ctx.code_block_first_pass() { let previous_symbol = ctx .namespace() .module(engines) diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs b/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs index 45674a7d95e..15266d2d2a7 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/impl_trait.rs @@ -646,7 +646,7 @@ fn type_check_trait_implementation( let type_engine = ctx.engines.te(); let decl_engine = ctx.engines.de(); let engines = ctx.engines(); - let collecting_unifications = ctx.collecting_unifications(); + let code_block_first_pass = ctx.code_block_first_pass(); // Check to see if the type that we are implementing for implements the // supertraits of this trait. @@ -665,7 +665,7 @@ fn type_check_trait_implementation( block_span, engines, TryInsertingTraitImplOnFailure::Yes, - collecting_unifications.into(), + code_block_first_pass.into(), ) })?; @@ -807,7 +807,7 @@ fn type_check_trait_implementation( type_decl.subst( &trait_type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); // Remove this type from the checklist. @@ -881,7 +881,7 @@ fn type_check_trait_implementation( impl_method.subst( &trait_type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); // Remove this method from the checklist. @@ -907,7 +907,7 @@ fn type_check_trait_implementation( const_decl.subst( &trait_type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); // Remove this constant from the checklist. @@ -980,7 +980,7 @@ fn type_check_trait_implementation( method.replace_decls(&decl_mapping, handler, &mut ctx)?; method.subst( &type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); all_items_refs.push(TyImplItem::Fn( decl_engine @@ -996,7 +996,7 @@ fn type_check_trait_implementation( const_decl.replace_decls(&decl_mapping, handler, &mut ctx)?; const_decl.subst( &type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); all_items_refs.push(TyImplItem::Constant(decl_engine.insert( const_decl, @@ -1007,7 +1007,7 @@ fn type_check_trait_implementation( let mut type_decl = (*decl_engine.get_type(decl_ref)).clone(); type_decl.subst( &type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); all_items_refs.push(TyImplItem::Type(decl_engine.insert( type_decl.clone(), @@ -1153,14 +1153,14 @@ fn type_check_impl_method( let mut impl_method_param_type_id = impl_method_param.type_argument.type_id; impl_method_param_type_id.subst( &ctx.type_subst(), - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); let mut impl_method_signature_param_type_id = impl_method_signature_param.type_argument.type_id; impl_method_signature_param_type_id.subst( &ctx.type_subst(), - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); if !UnifyCheck::non_dynamic_equality(engines).check( @@ -1233,14 +1233,14 @@ fn type_check_impl_method( let mut impl_method_return_type_id = impl_method.return_type.type_id; impl_method_return_type_id.subst( &ctx.type_subst(), - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); let mut impl_method_signature_return_type_type_id = impl_method_signature.return_type.type_id; impl_method_signature_return_type_type_id.subst( &ctx.type_subst(), - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); if !UnifyCheck::non_dynamic_equality(engines).check( @@ -1349,13 +1349,13 @@ fn type_check_const_decl( let mut const_decl_type_id = const_decl.type_ascription.type_id; const_decl_type_id.subst( &ctx.type_subst(), - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); let mut const_decl_signature_type_id = const_decl_signature.type_ascription.type_id; const_decl_signature_type_id.subst( &ctx.type_subst(), - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); // unify the types from the constant with the constant signature diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs index de81f68bb27..552bab4bba8 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs @@ -358,7 +358,7 @@ impl TyTraitDecl { let r = if method .subst( &type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ) .has_changes() { @@ -380,7 +380,7 @@ impl TyTraitDecl { let r = if const_decl .subst( &type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ) .has_changes() { @@ -399,7 +399,7 @@ impl TyTraitDecl { let r = if t .subst( &type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ) .has_changes() { @@ -456,7 +456,7 @@ impl TyTraitDecl { let mut method = (*decl_engine.get_trait_fn(decl_ref)).clone(); method.subst( &type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); all_items.push(TyImplItem::Fn( decl_engine @@ -487,7 +487,7 @@ impl TyTraitDecl { let mut method = (*decl_engine.get_function(decl_ref)).clone(); method.subst( &type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); all_items.push(TyImplItem::Fn( ctx.engines @@ -503,7 +503,7 @@ impl TyTraitDecl { let mut const_decl = (*decl_engine.get_constant(decl_ref)).clone(); const_decl.subst( &type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); all_items.push(TyImplItem::Constant(decl_engine.insert( const_decl, @@ -514,7 +514,7 @@ impl TyTraitDecl { let mut type_decl = (*decl_engine.get_type(decl_ref)).clone(); type_decl.subst( &type_mapping, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); all_items.push(TyImplItem::Type(decl_engine.insert( type_decl, diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs index 7cab1f82a57..f7505d07b0a 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression.rs @@ -1643,10 +1643,14 @@ impl ty::TyExpression { // type check the address and make sure it is let err_span = address.span().clone(); let address_expr = { + // We want to type check the address expression as we do in the second pass, otherwise we get + // mismatched types while comparing TypeInfo::ContractCaller which is the return type of + // TyExpressionVariant::AbiCast. let ctx = ctx .by_ref() .with_help_text("An address that is being ABI cast must be of type b256") - .with_type_annotation(type_engine.insert(engines, TypeInfo::B256, None)); + .with_type_annotation(type_engine.insert(engines, TypeInfo::B256, None)) + .with_code_block_first_pass(false); ty::TyExpression::type_check(handler, ctx, address) .unwrap_or_else(|err| ty::TyExpression::error(err, err_span, engines)) }; diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs index a3f299027b9..420c4257eb0 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/function_application.rs @@ -73,7 +73,7 @@ pub(crate) fn instantiate_function_application( { cached_fn_ref } else { - if !ctx.collecting_unifications() { + if !ctx.code_block_first_pass() { // 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. @@ -102,7 +102,7 @@ pub(crate) fn instantiate_function_application( ) .with_parent(decl_engine, (*function_decl_ref.id()).into()); - if !ctx.collecting_unifications() + if !ctx.code_block_first_pass() && method_sig.is_concrete(engines) && function_is_type_check_finalized && !function_is_trait_method_dummy 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 0ae7d765bbd..8dfcd358bfb 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 @@ -672,14 +672,14 @@ pub(crate) fn type_check_method_application( ); method.subst( &type_subst, - &SubstTypesContext::new(engines, !ctx.collecting_unifications()), + &SubstTypesContext::new(engines, !ctx.code_block_first_pass()), ); } } } } - if !ctx.collecting_unifications() { + if !ctx.code_block_first_pass() { // 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. @@ -702,7 +702,7 @@ pub(crate) fn type_check_method_application( method_return_type_id = method.return_type.type_id; decl_engine.replace(*fn_ref.id(), method.clone()); - if !ctx.collecting_unifications() + if !ctx.code_block_first_pass() && method_sig.is_concrete(engines) && method.is_type_check_finalized && !method.is_trait_method_dummy diff --git a/sway-core/src/semantic_analysis/namespace/mod.rs b/sway-core/src/semantic_analysis/namespace/mod.rs index 00802345672..5b723fa193d 100644 --- a/sway-core/src/semantic_analysis/namespace/mod.rs +++ b/sway-core/src/semantic_analysis/namespace/mod.rs @@ -14,7 +14,7 @@ pub use namespace::Namespace; pub use namespace::TryInsertingTraitImplOnFailure; pub use root::ResolvedDeclaration; pub use root::Root; -pub(super) use trait_map::CollectingUnification; +pub(super) use trait_map::CodeBlockFirstPass; pub(super) use trait_map::IsExtendingExistingImpl; pub(super) use trait_map::IsImplSelf; pub(super) use trait_map::ResolvedTraitImplItem; diff --git a/sway-core/src/semantic_analysis/namespace/root.rs b/sway-core/src/semantic_analysis/namespace/root.rs index 591fd5e8ec9..a9da70d1881 100644 --- a/sway-core/src/semantic_analysis/namespace/root.rs +++ b/sway-core/src/semantic_analysis/namespace/root.rs @@ -378,7 +378,7 @@ impl Root { .filter_by_type_item_import( type_id, engines, - super::CollectingUnification::No, + super::CodeBlockFirstPass::No, ), engines, ); diff --git a/sway-core/src/semantic_analysis/namespace/trait_map.rs b/sway-core/src/semantic_analysis/namespace/trait_map.rs index 69aad5db10f..6d1be290b42 100644 --- a/sway-core/src/semantic_analysis/namespace/trait_map.rs +++ b/sway-core/src/semantic_analysis/namespace/trait_map.rs @@ -30,17 +30,17 @@ use crate::{ use super::TryInsertingTraitImplOnFailure; #[derive(Clone)] -pub enum CollectingUnification { +pub enum CodeBlockFirstPass { Yes, No, } -impl From for CollectingUnification { +impl From for CodeBlockFirstPass { fn from(value: bool) -> Self { if value { - CollectingUnification::Yes + CodeBlockFirstPass::Yes } else { - CollectingUnification::No + CodeBlockFirstPass::No } } } @@ -570,10 +570,10 @@ impl TraitMap { &mut self, engines: &Engines, type_id: TypeId, - collecting_unifications: CollectingUnification, + code_block_first_pass: CodeBlockFirstPass, ) { self.extend( - self.filter_by_type(type_id, engines, collecting_unifications), + self.filter_by_type(type_id, engines, code_block_first_pass), engines, ); } @@ -746,7 +746,7 @@ impl TraitMap { &self, type_id: TypeId, engines: &Engines, - collecting_unifications: CollectingUnification, + code_block_first_pass: CodeBlockFirstPass, ) -> TraitMap { let unify_checker = UnifyCheck::constraint_subset(engines); @@ -755,7 +755,7 @@ impl TraitMap { let mut all_types = type_id.extract_inner_types(engines, IncludeSelf::No); all_types.insert(type_id); let all_types = all_types.into_iter().collect::>(); - self.filter_by_type_inner(engines, all_types, decider, collecting_unifications) + self.filter_by_type_inner(engines, all_types, decider, code_block_first_pass) } /// Filters the entries in `self` with the given [TypeId] `type_id` and @@ -820,7 +820,7 @@ impl TraitMap { &self, type_id: TypeId, engines: &Engines, - collecting_unifications: CollectingUnification, + code_block_first_pass: CodeBlockFirstPass, ) -> TraitMap { let unify_checker = UnifyCheck::constraint_subset(engines); let unify_checker_for_item_import = UnifyCheck::non_generic_constraint_subset(engines); @@ -833,7 +833,7 @@ impl TraitMap { engines, vec![type_id], decider, - collecting_unifications.clone(), + code_block_first_pass.clone(), ); let all_types = type_id .extract_inner_types(engines, IncludeSelf::No) @@ -843,7 +843,7 @@ impl TraitMap { let decider2 = |left: TypeId, right: TypeId| unify_checker.check(left, right); trait_map.extend( - self.filter_by_type_inner(engines, all_types, decider2, collecting_unifications), + self.filter_by_type_inner(engines, all_types, decider2, code_block_first_pass), engines, ); trait_map @@ -854,7 +854,7 @@ impl TraitMap { engines: &Engines, mut all_types: Vec, decider: impl Fn(TypeId, TypeId) -> bool, - collecting_unifications: CollectingUnification, + code_block_first_pass: CodeBlockFirstPass, ) -> TraitMap { let type_engine = engines.te(); let decl_engine = engines.de(); @@ -908,7 +908,7 @@ impl TraitMap { &type_mapping, &SubstTypesContext::new( engines, - matches!(collecting_unifications, CollectingUnification::No), + matches!(code_block_first_pass, CodeBlockFirstPass::No), ), ); let trait_items: TraitItems = map_trait_items @@ -927,8 +927,8 @@ impl TraitMap { &SubstTypesContext::new( engines, matches!( - collecting_unifications, - CollectingUnification::No + code_block_first_pass, + CodeBlockFirstPass::No ), ), ); @@ -952,10 +952,7 @@ impl TraitMap { &type_mapping, &SubstTypesContext::new( engines, - matches!( - collecting_unifications, - CollectingUnification::No - ), + matches!(code_block_first_pass, CodeBlockFirstPass::No), ), ); let new_ref = decl_engine.insert( @@ -973,10 +970,7 @@ impl TraitMap { &type_mapping, &SubstTypesContext::new( engines, - matches!( - collecting_unifications, - CollectingUnification::No - ), + matches!(code_block_first_pass, CodeBlockFirstPass::No), ), ); let new_ref = decl_engine.insert( @@ -1342,7 +1336,7 @@ impl TraitMap { access_span: &Span, engines: &Engines, try_inserting_trait_impl_on_failure: TryInsertingTraitImplOnFailure, - collecting_unifications: CollectingUnification, + code_block_first_pass: CodeBlockFirstPass, ) -> Result<(), ErrorEmitted> { let type_engine = engines.te(); @@ -1373,7 +1367,7 @@ impl TraitMap { access_span, engines, try_inserting_trait_impl_on_failure, - collecting_unifications, + code_block_first_pass, ) { Ok(()) => { self.satisfied_cache.insert(hash); @@ -1392,7 +1386,7 @@ impl TraitMap { access_span: &Span, engines: &Engines, try_inserting_trait_impl_on_failure: TryInsertingTraitImplOnFailure, - collecting_unifications: CollectingUnification, + code_block_first_pass: CodeBlockFirstPass, ) -> Result<(), ErrorEmitted> { let type_engine = engines.te(); @@ -1496,7 +1490,7 @@ impl TraitMap { try_inserting_trait_impl_on_failure, TryInsertingTraitImplOnFailure::Yes ) { - self.insert_for_type(engines, type_id, collecting_unifications.clone()); + self.insert_for_type(engines, type_id, code_block_first_pass.clone()); return self.check_if_trait_constraints_are_satisfied_for_type( handler, type_id, @@ -1504,7 +1498,7 @@ impl TraitMap { access_span, engines, TryInsertingTraitImplOnFailure::No, - collecting_unifications.clone(), + code_block_first_pass.clone(), ); } else { let mut type_arguments_string = "".to_string(); diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs index 1ced9fd248c..cb0b637227b 100644 --- a/sway-core/src/semantic_analysis/type_check_context.rs +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -95,7 +95,13 @@ pub struct TypeCheckContext<'a> { /// Indicates when semantic analysis is type checking storage declaration. storage_declaration: bool, + // Indicates when we are collecting unifications. collecting_unifications: bool, + + // Indicates when we are doing the first pass of the code block type checking. + // In some nested places of the first pass we eant to disable the first pass optimizations + // To disable those optimizations we can set this to false. + code_block_first_pass: bool, } impl<'a> TypeCheckContext<'a> { @@ -122,6 +128,7 @@ impl<'a> TypeCheckContext<'a> { storage_declaration: false, experimental, collecting_unifications: false, + code_block_first_pass: false, } } @@ -162,6 +169,7 @@ impl<'a> TypeCheckContext<'a> { storage_declaration: false, experimental, collecting_unifications: false, + code_block_first_pass: false, } } @@ -191,6 +199,7 @@ impl<'a> TypeCheckContext<'a> { storage_declaration: self.storage_declaration, experimental: self.experimental, collecting_unifications: self.collecting_unifications, + code_block_first_pass: self.code_block_first_pass, } } @@ -217,6 +226,7 @@ impl<'a> TypeCheckContext<'a> { storage_declaration: self.storage_declaration, experimental: self.experimental, collecting_unifications: self.collecting_unifications, + code_block_first_pass: self.code_block_first_pass, }; with_scoped_ctx(ctx) } @@ -244,6 +254,7 @@ impl<'a> TypeCheckContext<'a> { storage_declaration: self.storage_declaration, experimental: self.experimental, collecting_unifications: self.collecting_unifications, + code_block_first_pass: self.code_block_first_pass, }; Ok((with_scoped_ctx(ctx)?, namespace)) } @@ -362,6 +373,13 @@ impl<'a> TypeCheckContext<'a> { } } + pub(crate) fn with_code_block_first_pass(self, value: bool) -> Self { + Self { + code_block_first_pass: value, + ..self + } + } + /// Map this `TypeCheckContext` instance to a new one with /// `disallow_functions` set to `true`. pub(crate) fn disallow_functions(self) -> Self { @@ -437,6 +455,10 @@ impl<'a> TypeCheckContext<'a> { self.collecting_unifications } + pub(crate) fn code_block_first_pass(&self) -> bool { + self.code_block_first_pass + } + // Provide some convenience functions around the inner context. /// Short-hand for calling the `monomorphize` function in the type engine @@ -1439,11 +1461,7 @@ impl<'a> TypeCheckContext<'a> { src_mod .current_items() .implemented_traits - .filter_by_type_item_import( - type_id, - engines, - self.collecting_unifications().into(), - ), + .filter_by_type_item_import(type_id, engines, self.code_block_first_pass().into()), engines, ); @@ -1739,12 +1757,12 @@ impl<'a> TypeCheckContext<'a> { pub(crate) fn insert_trait_implementation_for_type(&mut self, type_id: TypeId) { let engines = self.engines; - let collecting_unifications = self.collecting_unifications(); + let code_block_first_pass = self.code_block_first_pass(); self.namespace_mut() .module_mut(engines) .current_items_mut() .implemented_traits - .insert_for_type(engines, type_id, collecting_unifications.into()); + .insert_for_type(engines, type_id, code_block_first_pass.into()); } pub fn check_type_impls_traits( @@ -1754,7 +1772,7 @@ impl<'a> TypeCheckContext<'a> { ) -> bool { let handler = Handler::default(); let engines = self.engines; - let collecting_unifications = self.collecting_unifications(); + let code_block_first_pass = self.code_block_first_pass(); self.namespace_mut() .module_mut(engines) .current_items_mut() @@ -1766,7 +1784,7 @@ impl<'a> TypeCheckContext<'a> { &Span::dummy(), engines, crate::namespace::TryInsertingTraitImplOnFailure::Yes, - collecting_unifications.into(), + code_block_first_pass.into(), ) .is_ok() } diff --git a/sway-core/src/type_system/ast_elements/type_parameter.rs b/sway-core/src/type_system/ast_elements/type_parameter.rs index bc85cc24247..40cd55f1f50 100644 --- a/sway-core/src/type_system/ast_elements/type_parameter.rs +++ b/sway-core/src/type_system/ast_elements/type_parameter.rs @@ -507,8 +507,8 @@ impl TypeParameter { .. } = type_param; - let collecting_unifications = ctx.collecting_unifications(); - if !collecting_unifications { + let code_block_first_pass = ctx.code_block_first_pass(); + if !code_block_first_pass { // Check to see if the trait constraints are satisfied. match ctx .namespace_mut() @@ -522,7 +522,7 @@ impl TypeParameter { access_span, engines, TryInsertingTraitImplOnFailure::Yes, - collecting_unifications.into(), + code_block_first_pass.into(), ) { Ok(res) => res, Err(_) => continue, diff --git a/sway-core/src/type_system/id.rs b/sway-core/src/type_system/id.rs index d029cc2d772..709a1bf7a23 100644 --- a/sway-core/src/type_system/id.rs +++ b/sway-core/src/type_system/id.rs @@ -519,7 +519,7 @@ impl TypeId { span: &Span, type_param: Option, ) -> Result<(), ErrorEmitted> { - if ctx.collecting_unifications() { + if ctx.code_block_first_pass() { return Ok(()); } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/Forc.lock new file mode 100644 index 00000000000..1502892f25d --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/Forc.lock @@ -0,0 +1,13 @@ +[[package]] +name = "contract_calls_unwrapped_contract_id" +source = "member" +dependencies = ["std"] + +[[package]] +name = "core" +source = "path+from-root-A615F9B9DE584E81" + +[[package]] +name = "std" +source = "path+from-root-A615F9B9DE584E81" +dependencies = ["core"] diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/Forc.toml new file mode 100644 index 00000000000..00360995cb3 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/Forc.toml @@ -0,0 +1,9 @@ +[project] +name = "contract_calls_unwrapped_contract_id" +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +implicit-std = false + +[dependencies] +std = { path = "../../../../../../../sway-lib-std" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/src/main.sw new file mode 100644 index 00000000000..1ca64650c93 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/src/main.sw @@ -0,0 +1,18 @@ +script; + +const ADDRESS: b256 = 0x000000000000000000000000000000000000000000000000000000000000002A; +const IDENTITY: Identity = Identity::ContractId(ContractId::from(ADDRESS)); + +abi MyAbi { + fn abi_method(); +} + +impl MyAbi for Contract { + fn abi_method() { } +} + +fn main() -> u64 { + let caller = abi(MyAbi, IDENTITY.as_contract_id().unwrap().into()); + caller.abi_method(); + 0 +} diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/test.toml b/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/test.toml new file mode 100644 index 00000000000..f52915a4c45 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/contract_calls_unwrapped_contract_id/test.toml @@ -0,0 +1,5 @@ +category = "compile" + +validate_abi = false +validate_storage_slots = false +expected_warnings = 2