diff --git a/forc-pkg/src/manifest.rs b/forc-pkg/src/manifest.rs index cc5260aa234..489424abdfa 100644 --- a/forc-pkg/src/manifest.rs +++ b/forc-pkg/src/manifest.rs @@ -8,7 +8,7 @@ use std::{ sync::Arc, }; -use sway_core::{parse, TreeType}; +use sway_core::{parse, type_system::TypeEngine, TreeType}; use sway_utils::constants; type PatchMap = BTreeMap; @@ -182,7 +182,8 @@ impl ManifestFile { /// Parse and return the associated project's program type. pub fn program_type(&self) -> Result { let entry_string = self.entry_string()?; - let parse_res = parse(entry_string, None); + let type_engine = TypeEngine::default(); + let parse_res = parse(entry_string, None, &type_engine); match parse_res.value { Some(parse_program) => Ok(parse_program.kind), None => bail!(parsing_failed(&self.project.name, parse_res.errors)), diff --git a/forc-pkg/src/pkg.rs b/forc-pkg/src/pkg.rs index 5f237871c77..94461199cff 100644 --- a/forc-pkg/src/pkg.rs +++ b/forc-pkg/src/pkg.rs @@ -24,8 +24,9 @@ use std::{ str::FromStr, }; use sway_core::{ - semantic_analysis::namespace, source_map::SourceMap, types::*, BytecodeCompilationResult, - CompileAstResult, CompileError, CompileResult, ParseProgram, TreeType, + semantic_analysis::namespace, source_map::SourceMap, type_system::TypeEngine, types::*, + BytecodeCompilationResult, CompileAstResult, CompileError, CompileResult, ParseProgram, + TreeType, }; use sway_types::JsonABI; use sway_utils::constants; @@ -1932,18 +1933,19 @@ pub fn check( sway_core::clear_lazy_statics(); let mut namespace_map = Default::default(); let mut source_map = SourceMap::new(); + let type_engine = TypeEngine::default(); for (i, &node) in plan.compilation_order.iter().enumerate() { let dep_namespace = dependency_namespace(&namespace_map, &plan.graph, node); let pkg = &plan.graph[node]; let manifest = &plan.manifest_map()[&pkg.id()]; - let parsed_result = parse(manifest, silent_mode)?; + let parsed_result = parse(manifest, silent_mode, &type_engine)?; let parse_program = match &parsed_result.value { None => bail!("unable to parse"), Some(program) => program, }; - let ast_result = sway_core::parsed_to_ast(parse_program, dep_namespace); + let ast_result = sway_core::parsed_to_ast(parse_program, dep_namespace, &type_engine); let typed_program = match &ast_result { CompileAstResult::Failure { .. } => bail!("unable to type check"), @@ -1968,6 +1970,7 @@ pub fn check( pub fn parse( manifest: &ManifestFile, silent_mode: bool, + type_engine: &TypeEngine, ) -> anyhow::Result> { let profile = BuildProfile { silent: silent_mode, @@ -1975,7 +1978,11 @@ pub fn parse( }; let source = manifest.entry_string()?; let sway_build_config = sway_build_config(manifest.dir(), &manifest.entry_path(), &profile)?; - Ok(sway_core::parse(source, Some(&sway_build_config))) + Ok(sway_core::parse( + source, + Some(&sway_build_config), + type_engine, + )) } /// Attempt to find a `Forc.toml` with the given project name within the given directory. diff --git a/sway-core/src/convert_parse_tree.rs b/sway-core/src/convert_parse_tree.rs index cca19a79a6d..e6f303bde7b 100644 --- a/sway-core/src/convert_parse_tree.rs +++ b/sway-core/src/convert_parse_tree.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use crate::type_system::{TraitConstraint, TypeArgument, TypeBinding, TypeParameter}; +use crate::type_system::{TraitConstraint, TypeArgument, TypeBinding, TypeEngine, TypeParameter}; use { crate::{ @@ -8,7 +8,7 @@ use { STORAGE_PURITY_ATTRIBUTE_NAME, STORAGE_PURITY_READ_NAME, STORAGE_PURITY_WRITE_NAME, }, error::{err, ok, CompileError, CompileResult, CompileWarning}, - type_system::{insert_type, AbiName, IntegerBits}, + type_system::{AbiName, IntegerBits}, AbiCastExpression, AbiDeclaration, ArrayIndexExpression, AsmExpression, AsmOp, AsmRegister, AsmRegisterDeclaration, AstNode, AstNodeContent, CallPath, CodeBlock, ConstantDeclaration, Declaration, DelineatedPathExpression, EnumDeclaration, EnumVariant, Expression, @@ -240,7 +240,10 @@ impl Spanned for ConvertParseTreeError { } } -pub fn convert_parse_tree(module: Module) -> CompileResult<(TreeType, ParseTree)> { +pub fn convert_parse_tree( + module: Module, + type_engine: &TypeEngine, +) -> CompileResult<(TreeType, ParseTree)> { let mut ec = ErrorContext { warnings: Vec::new(), errors: Vec::new(), @@ -251,7 +254,7 @@ pub fn convert_parse_tree(module: Module) -> CompileResult<(TreeType, ParseTree) ModuleKind::Predicate { .. } => TreeType::Predicate, ModuleKind::Library { ref name, .. } => TreeType::Library { name: name.clone() }, }; - let res = module_to_sway_parse_tree(&mut ec, module); + let res = module_to_sway_parse_tree(type_engine, &mut ec, module); let ErrorContext { warnings, errors } = ec; match res { Ok(parse_tree) => ok((tree_type, parse_tree), warnings, errors), @@ -260,6 +263,7 @@ pub fn convert_parse_tree(module: Module) -> CompileResult<(TreeType, ParseTree) } pub fn module_to_sway_parse_tree( + type_engine: &TypeEngine, ec: &mut ErrorContext, module: Module, ) -> Result { @@ -278,7 +282,7 @@ pub fn module_to_sway_parse_tree( .collect() }; for item in module.items { - let ast_nodes = item_to_ast_nodes(ec, item)?; + let ast_nodes = item_to_ast_nodes(type_engine, ec, item)?; root_nodes.extend(ast_nodes); } root_nodes @@ -286,7 +290,11 @@ pub fn module_to_sway_parse_tree( Ok(ParseTree { span, root_nodes }) } -fn item_to_ast_nodes(ec: &mut ErrorContext, item: Item) -> Result, ErrorEmitted> { +fn item_to_ast_nodes( + type_engine: &TypeEngine, + ec: &mut ErrorContext, + item: Item, +) -> Result, ErrorEmitted> { let attributes = item_attrs_to_map(&item.attribute_list)?; let span = item.span(); @@ -299,47 +307,51 @@ fn item_to_ast_nodes(ec: &mut ErrorContext, item: Item) -> Result, .collect() } ItemKind::Struct(item_struct) => { - let struct_declaration = item_struct_to_struct_declaration(ec, item_struct)?; + let struct_declaration = + item_struct_to_struct_declaration(type_engine, ec, item_struct)?; vec![AstNodeContent::Declaration(Declaration::StructDeclaration( struct_declaration, ))] } ItemKind::Enum(item_enum) => { - let enum_declaration = item_enum_to_enum_declaration(ec, item_enum)?; + let enum_declaration = item_enum_to_enum_declaration(type_engine, ec, item_enum)?; vec![AstNodeContent::Declaration(Declaration::EnumDeclaration( enum_declaration, ))] } ItemKind::Fn(item_fn) => { - let function_declaration = item_fn_to_function_declaration(ec, item_fn, &attributes)?; + let function_declaration = + item_fn_to_function_declaration(type_engine, ec, item_fn, &attributes)?; vec![AstNodeContent::Declaration( Declaration::FunctionDeclaration(function_declaration), )] } ItemKind::Trait(item_trait) => { - let trait_declaration = item_trait_to_trait_declaration(ec, item_trait)?; + let trait_declaration = item_trait_to_trait_declaration(type_engine, ec, item_trait)?; vec![AstNodeContent::Declaration(Declaration::TraitDeclaration( trait_declaration, ))] } ItemKind::Impl(item_impl) => { - let declaration = item_impl_to_declaration(ec, item_impl)?; + let declaration = item_impl_to_declaration(type_engine, ec, item_impl)?; vec![AstNodeContent::Declaration(declaration)] } ItemKind::Abi(item_abi) => { - let abi_declaration = item_abi_to_abi_declaration(ec, item_abi)?; + let abi_declaration = item_abi_to_abi_declaration(type_engine, ec, item_abi)?; vec![AstNodeContent::Declaration(Declaration::AbiDeclaration( abi_declaration, ))] } ItemKind::Const(item_const) => { - let constant_declaration = item_const_to_constant_declaration(ec, item_const)?; + let constant_declaration = + item_const_to_constant_declaration(type_engine, ec, item_const)?; vec![AstNodeContent::Declaration( Declaration::ConstantDeclaration(constant_declaration), )] } ItemKind::Storage(item_storage) => { - let storage_declaration = item_storage_to_storage_declaration(ec, item_storage)?; + let storage_declaration = + item_storage_to_storage_declaration(type_engine, ec, item_storage)?; vec![AstNodeContent::Declaration( Declaration::StorageDeclaration(storage_declaration), )] @@ -487,6 +499,7 @@ fn use_tree_to_use_statements( } fn item_struct_to_struct_declaration( + type_engine: &TypeEngine, ec: &mut ErrorContext, item_struct: ItemStruct, ) -> Result { @@ -496,7 +509,7 @@ fn item_struct_to_struct_declaration( .fields .into_inner() .into_iter() - .map(|type_field| type_field_to_struct_field(ec, type_field)) + .map(|type_field| type_field_to_struct_field(type_engine, ec, type_field)) .collect::, _>>()?; if fields.iter().any( @@ -524,6 +537,7 @@ fn item_struct_to_struct_declaration( name: item_struct.name, fields, type_parameters: generic_params_opt_to_type_parameters( + type_engine, ec, item_struct.generics, item_struct.where_clause_opt, @@ -535,6 +549,7 @@ fn item_struct_to_struct_declaration( } fn item_enum_to_enum_declaration( + type_engine: &TypeEngine, ec: &mut ErrorContext, item_enum: ItemEnum, ) -> Result { @@ -545,7 +560,7 @@ fn item_enum_to_enum_declaration( .into_inner() .into_iter() .enumerate() - .map(|(tag, type_field)| type_field_to_enum_variant(ec, type_field, tag)) + .map(|(tag, type_field)| type_field_to_enum_variant(type_engine, ec, type_field, tag)) .collect::, _>>()?; if variants.iter().any(|variant| { @@ -572,6 +587,7 @@ fn item_enum_to_enum_declaration( let enum_declaration = EnumDeclaration { name: item_enum.name, type_parameters: generic_params_opt_to_type_parameters( + type_engine, ec, item_enum.generics, item_enum.where_clause_opt, @@ -584,6 +600,7 @@ fn item_enum_to_enum_declaration( } fn item_fn_to_function_declaration( + type_engine: &TypeEngine, ec: &mut ErrorContext, item_fn: ItemFn, attributes: &AttributesMap, @@ -597,17 +614,19 @@ fn item_fn_to_function_declaration( purity: get_attributed_purity(ec, attributes)?, name: item_fn.fn_signature.name, visibility: pub_token_opt_to_visibility(item_fn.fn_signature.visibility), - body: braced_code_block_contents_to_code_block(ec, item_fn.body)?, + body: braced_code_block_contents_to_code_block(type_engine, ec, item_fn.body)?, parameters: fn_args_to_function_parameters( + type_engine, ec, item_fn.fn_signature.arguments.into_inner(), )?, span, return_type: match item_fn.fn_signature.return_type_opt { - Some((_right_arrow, ty)) => ty_to_type_info(ec, ty)?, + Some((_right_arrow, ty)) => ty_to_type_info(type_engine, ec, ty)?, None => TypeInfo::Tuple(Vec::new()), }, type_parameters: generic_params_opt_to_type_parameters( + type_engine, ec, item_fn.fn_signature.generics, item_fn.fn_signature.where_clause_opt, @@ -649,6 +668,7 @@ fn get_attributed_purity( } fn item_trait_to_trait_declaration( + type_engine: &TypeEngine, ec: &mut ErrorContext, item_trait: ItemTrait, ) -> Result { @@ -660,7 +680,7 @@ fn item_trait_to_trait_declaration( .into_iter() .map(|(fn_signature, _semicolon_token)| { let attributes = item_attrs_to_map(&fn_signature.attribute_list)?; - fn_signature_to_trait_fn(ec, fn_signature.value, &attributes) + fn_signature_to_trait_fn(type_engine, ec, fn_signature.value, &attributes) }) .collect::>()? }; @@ -671,7 +691,7 @@ fn item_trait_to_trait_declaration( .into_iter() .map(|item_fn| { let attributes = item_attrs_to_map(&item_fn.attribute_list)?; - item_fn_to_function_declaration(ec, item_fn.value, &attributes) + item_fn_to_function_declaration(type_engine, ec, item_fn.value, &attributes) }) .collect::>()?, }; @@ -690,12 +710,13 @@ fn item_trait_to_trait_declaration( } fn item_impl_to_declaration( + type_engine: &TypeEngine, ec: &mut ErrorContext, item_impl: ItemImpl, ) -> Result { let block_span = item_impl.span(); let type_implementing_for_span = item_impl.ty.span(); - let type_implementing_for = ty_to_type_info(ec, item_impl.ty)?; + let type_implementing_for = ty_to_type_info(type_engine, ec, item_impl.ty)?; let functions = { item_impl .contents @@ -703,12 +724,13 @@ fn item_impl_to_declaration( .into_iter() .map(|item| { let attributes = item_attrs_to_map(&item.attribute_list)?; - item_fn_to_function_declaration(ec, item.value, &attributes) + item_fn_to_function_declaration(type_engine, ec, item.value, &attributes) }) .collect::>()? }; let type_parameters = generic_params_opt_to_type_parameters( + type_engine, ec, item_impl.generic_params_opt, item_impl.where_clause_opt, @@ -740,6 +762,7 @@ fn item_impl_to_declaration( } fn item_abi_to_abi_declaration( + type_engine: &TypeEngine, ec: &mut ErrorContext, item_abi: ItemAbi, ) -> Result { @@ -753,7 +776,7 @@ fn item_abi_to_abi_declaration( .into_iter() .map(|(fn_signature, _semicolon_token)| { let attributes = item_attrs_to_map(&fn_signature.attribute_list)?; - fn_signature_to_trait_fn(ec, fn_signature.value, &attributes) + fn_signature_to_trait_fn(type_engine, ec, fn_signature.value, &attributes) }) .collect::>()? }, @@ -764,7 +787,7 @@ fn item_abi_to_abi_declaration( .into_iter() .map(|item_fn| { let attributes = item_attrs_to_map(&item_fn.attribute_list)?; - item_fn_to_function_declaration(ec, item_fn.value, &attributes) + item_fn_to_function_declaration(type_engine, ec, item_fn.value, &attributes) }) .collect::>()?, }, @@ -773,21 +796,23 @@ fn item_abi_to_abi_declaration( } fn item_const_to_constant_declaration( + type_engine: &TypeEngine, ec: &mut ErrorContext, item_const: ItemConst, ) -> Result { Ok(ConstantDeclaration { name: item_const.name, type_ascription: match item_const.ty_opt { - Some((_colon_token, ty)) => ty_to_type_info(ec, ty)?, + Some((_colon_token, ty)) => ty_to_type_info(type_engine, ec, ty)?, None => TypeInfo::Unknown, }, - value: expr_to_expression(ec, item_const.expr)?, + value: expr_to_expression(type_engine, ec, item_const.expr)?, visibility: pub_token_opt_to_visibility(item_const.visibility), }) } fn item_storage_to_storage_declaration( + type_engine: &TypeEngine, ec: &mut ErrorContext, item_storage: ItemStorage, ) -> Result { @@ -797,7 +822,7 @@ fn item_storage_to_storage_declaration( .fields .into_inner() .into_iter() - .map(|storage_field| storage_field_to_storage_field(ec, storage_field)) + .map(|storage_field| storage_field_to_storage_field(type_engine, ec, storage_field)) .collect::>()?; // Make sure each storage field is declared once @@ -820,6 +845,7 @@ fn item_storage_to_storage_declaration( } fn type_field_to_struct_field( + type_engine: &TypeEngine, ec: &mut ErrorContext, type_field: TypeField, ) -> Result { @@ -827,7 +853,7 @@ fn type_field_to_struct_field( let type_span = type_field.ty.span(); let struct_field = StructField { name: type_field.name, - type_info: ty_to_type_info(ec, type_field.ty)?, + type_info: ty_to_type_info(type_engine, ec, type_field.ty)?, span, type_span, }; @@ -835,6 +861,7 @@ fn type_field_to_struct_field( } fn generic_params_opt_to_type_parameters( + type_engine: &TypeEngine, ec: &mut ErrorContext, generic_params_opt: Option, where_clause_opt: Option, @@ -854,7 +881,7 @@ fn generic_params_opt_to_type_parameters( .into_inner() .into_iter() .map(|ident| TypeParameter { - type_id: insert_type(TypeInfo::Custom { + type_id: type_engine.insert_type(TypeInfo::Custom { name: ident.clone(), type_arguments: None, }), @@ -906,6 +933,7 @@ fn pub_token_opt_to_visibility(pub_token_opt: Option) -> Visibility { } fn type_field_to_enum_variant( + type_engine: &TypeEngine, ec: &mut ErrorContext, type_field: TypeField, tag: usize, @@ -913,7 +941,7 @@ fn type_field_to_enum_variant( let span = type_field.span(); let enum_variant = EnumVariant { name: type_field.name, - type_info: ty_to_type_info(ec, type_field.ty)?, + type_info: ty_to_type_info(type_engine, ec, type_field.ty)?, tag, span, }; @@ -921,6 +949,7 @@ fn type_field_to_enum_variant( } fn braced_code_block_contents_to_code_block( + type_engine: &TypeEngine, ec: &mut ErrorContext, braced_code_block_contents: Braces, ) -> Result { @@ -929,11 +958,11 @@ fn braced_code_block_contents_to_code_block( let contents = { let mut contents = Vec::new(); for statement in code_block_contents.statements { - let ast_nodes = statement_to_ast_nodes(ec, statement)?; + let ast_nodes = statement_to_ast_nodes(type_engine, ec, statement)?; contents.extend(ast_nodes); } if let Some(expr) = code_block_contents.final_expr_opt { - let final_ast_node = expr_to_ast_node(ec, *expr, false)?; + let final_ast_node = expr_to_ast_node(type_engine, ec, *expr, false)?; contents.push(final_ast_node); } contents @@ -945,13 +974,14 @@ fn braced_code_block_contents_to_code_block( } fn fn_args_to_function_parameters( + type_engine: &TypeEngine, ec: &mut ErrorContext, fn_args: FnArgs, ) -> Result, ErrorEmitted> { let function_parameters = match fn_args { FnArgs::Static(args) => args .into_iter() - .map(|fn_arg| fn_arg_to_function_parameter(ec, fn_arg)) + .map(|fn_arg| fn_arg_to_function_parameter(type_engine, ec, fn_arg)) .collect::>()?, FnArgs::NonStatic { self_token, @@ -961,12 +991,12 @@ fn fn_args_to_function_parameters( let mut function_parameters = vec![FunctionParameter { name: Ident::new(self_token.span()), is_mutable: mutable_self.is_some(), - type_id: insert_type(TypeInfo::SelfType), + type_id: type_engine.insert_type(TypeInfo::SelfType), type_span: self_token.span(), }]; if let Some((_comma_token, args)) = args_opt { for arg in args { - let function_parameter = fn_arg_to_function_parameter(ec, arg)?; + let function_parameter = fn_arg_to_function_parameter(type_engine, ec, arg)?; function_parameters.push(function_parameter); } } @@ -1006,11 +1036,16 @@ fn type_name_to_type_info_opt(name: &Ident) -> Option { } } -fn ty_to_type_info(ec: &mut ErrorContext, ty: Ty) -> Result { +fn ty_to_type_info( + type_engine: &TypeEngine, + ec: &mut ErrorContext, + ty: Ty, +) -> Result { let type_info = match ty { - Ty::Path(path_type) => path_type_to_type_info(ec, path_type)?, + Ty::Path(path_type) => path_type_to_type_info(type_engine, ec, path_type)?, Ty::Tuple(parenthesized_ty_tuple_descriptor) => { TypeInfo::Tuple(ty_tuple_descriptor_to_type_arguments( + type_engine, ec, parenthesized_ty_tuple_descriptor.into_inner(), )?) @@ -1018,7 +1053,7 @@ fn ty_to_type_info(ec: &mut ErrorContext, ty: Ty) -> Result { let ty_array_descriptor = bracketed_ty_array_descriptor.into_inner(); TypeInfo::Array( - crate::type_system::insert_type(ty_to_type_info(ec, *ty_array_descriptor.ty)?), + type_engine.insert_type(ty_to_type_info(type_engine, ec, *ty_array_descriptor.ty)?), expr_to_usize(ec, *ty_array_descriptor.length)?, ) } @@ -1028,16 +1063,21 @@ fn ty_to_type_info(ec: &mut ErrorContext, ty: Ty) -> Result Result { +fn ty_to_type_argument( + type_engine: &TypeEngine, + ec: &mut ErrorContext, + ty: Ty, +) -> Result { let span = ty.span(); let type_argument = TypeArgument { - type_id: insert_type(ty_to_type_info(ec, ty)?), + type_id: type_engine.insert_type(ty_to_type_info(type_engine, ec, ty)?), span, }; Ok(type_argument) } fn fn_signature_to_trait_fn( + type_engine: &TypeEngine, ec: &mut ErrorContext, fn_signature: FnSignature, attributes: &AttributesMap, @@ -1049,9 +1089,13 @@ fn fn_signature_to_trait_fn( let trait_fn = TraitFn { name: fn_signature.name, purity: get_attributed_purity(ec, attributes)?, - parameters: fn_args_to_function_parameters(ec, fn_signature.arguments.into_inner())?, + parameters: fn_args_to_function_parameters( + type_engine, + ec, + fn_signature.arguments.into_inner(), + )?, return_type: match fn_signature.return_type_opt { - Some((_right_arrow_token, ty)) => ty_to_type_info(ec, ty)?, + Some((_right_arrow_token, ty)) => ty_to_type_info(type_engine, ec, ty)?, None => TypeInfo::Tuple(Vec::new()), }, return_type_span, @@ -1116,6 +1160,7 @@ fn path_type_to_call_path( } fn expr_to_ast_node( + type_engine: &TypeEngine, ec: &mut ErrorContext, expr: Expr, is_statement: bool, @@ -1124,7 +1169,7 @@ fn expr_to_ast_node( let ast_node = match expr { Expr::Return { expr_opt, .. } => { let expression = match expr_opt { - Some(expr) => expr_to_expression(ec, *expr)?, + Some(expr) => expr_to_expression(type_engine, ec, *expr)?, None => Expression { kind: ExpressionKind::Tuple(Vec::new()), span: span.clone(), @@ -1139,8 +1184,8 @@ fn expr_to_ast_node( condition, block, .. } => AstNode { content: AstNodeContent::WhileLoop(WhileLoop { - condition: expr_to_expression(ec, *condition)?, - body: braced_code_block_contents_to_code_block(ec, block)?, + condition: expr_to_expression(type_engine, ec, *condition)?, + body: braced_code_block_contents_to_code_block(type_engine, ec, block)?, }), span, }, @@ -1155,20 +1200,20 @@ fn expr_to_ast_node( } => match op_variant { ReassignmentOpVariant::Equals => AstNode { content: AstNodeContent::Declaration(Declaration::Reassignment(Reassignment { - lhs: assignable_to_reassignment_target(ec, assignable)?, - rhs: expr_to_expression(ec, *expr)?, + lhs: assignable_to_reassignment_target(type_engine, ec, assignable)?, + rhs: expr_to_expression(type_engine, ec, *expr)?, span: span.clone(), })), span, }, op_variant => { - let lhs = assignable_to_reassignment_target(ec, assignable.clone())?; + let lhs = assignable_to_reassignment_target(type_engine, ec, assignable.clone())?; let rhs = binary_op_call( op_variant.core_name(), op_span, span.clone(), - assignable_to_expression(ec, assignable)?, - expr_to_expression(ec, *expr)?, + assignable_to_expression(type_engine, ec, assignable)?, + expr_to_expression(type_engine, ec, *expr)?, )?; let content = AstNodeContent::Declaration(Declaration::Reassignment(Reassignment { @@ -1180,7 +1225,7 @@ fn expr_to_ast_node( } }, expr => { - let expression = expr_to_expression(ec, expr)?; + let expression = expr_to_expression(type_engine, ec, expr)?; if !is_statement { AstNode { content: AstNodeContent::ImplicitReturnExpression(expression), @@ -1198,27 +1243,29 @@ fn expr_to_ast_node( } fn abi_cast_args_to_abi_cast_expression( + type_engine: &TypeEngine, ec: &mut ErrorContext, args: Parens, ) -> Result, ErrorEmitted> { let AbiCastArgs { name, address, .. } = args.into_inner(); let abi_name = path_type_to_call_path(ec, name)?; - let address = Box::new(expr_to_expression(ec, *address)?); + let address = Box::new(expr_to_expression(type_engine, ec, *address)?); Ok(Box::new(AbiCastExpression { abi_name, address })) } fn struct_path_and_fields_to_struct_expression( + type_engine: &TypeEngine, ec: &mut ErrorContext, path: PathExpr, fields: Braces>, ) -> Result, ErrorEmitted> { - let call_path_binding = path_expr_to_call_path_binding(ec, path)?; + let call_path_binding = path_expr_to_call_path_binding(type_engine, ec, path)?; let fields = { fields .into_inner() .into_iter() .map(|expr_struct_field| { - expr_struct_field_to_struct_expression_field(ec, expr_struct_field) + expr_struct_field_to_struct_expression_field(type_engine, ec, expr_struct_field) }) .collect::>()? }; @@ -1229,6 +1276,7 @@ fn struct_path_and_fields_to_struct_expression( } fn method_call_fields_to_method_application_expression( + type_engine: &TypeEngine, ec: &mut ErrorContext, target: Box, name: Ident, @@ -1248,13 +1296,13 @@ fn method_call_fields_to_method_application_expression( .into_inner() .into_iter() .map(|expr_struct_field| { - expr_struct_field_to_struct_expression_field(ec, expr_struct_field) + expr_struct_field_to_struct_expression_field(type_engine, ec, expr_struct_field) }) .collect::>()?, }; let arguments = iter::once(*target) .chain(args.into_inner().into_iter()) - .map(|expr| expr_to_expression(ec, expr)) + .map(|expr| expr_to_expression(type_engine, ec, expr)) .collect::>()?; Ok(Box::new(MethodApplicationExpression { method_name_binding, @@ -1264,6 +1312,7 @@ fn method_call_fields_to_method_application_expression( } fn expr_func_app_to_expression_kind( + type_engine: &TypeEngine, ec: &mut ErrorContext, func: Box, args: Parens>, @@ -1298,7 +1347,7 @@ fn expr_func_app_to_expression_kind( } = maybe_method_segment; let (parent_type_arguments, parent_type_arguments_span) = match generics_opt { Some((_double_colon_token, generic_args)) => ( - generic_args_to_type_arguments(ec, generic_args.clone())?, + generic_args_to_type_arguments(type_engine, ec, generic_args.clone())?, Some(generic_args.span()), ), None => (Vec::new(), None), @@ -1335,7 +1384,7 @@ fn expr_func_app_to_expression_kind( } = prefix; let (parent_type_arguments, parent_type_arguments_span) = match generics_opt { Some((_double_colon_token, generic_args)) => ( - generic_args_to_type_arguments(ec, generic_args.clone())?, + generic_args_to_type_arguments(type_engine, ec, generic_args.clone())?, Some(generic_args.span()), ), None => (Vec::new(), None), @@ -1375,7 +1424,7 @@ fn expr_func_app_to_expression_kind( let arguments = { args.into_inner() .into_iter() - .map(|expr| expr_to_expression(ec, expr)) + .map(|expr| expr_to_expression(type_engine, ec, expr)) .collect::>()? }; let expression_kind = match method_type_opt { @@ -1403,7 +1452,7 @@ fn expr_func_app_to_expression_kind( }; let (method_type_arguments, method_type_arguments_span) = match generics_opt { Some((_double_colon_token, generic_args)) => ( - generic_args_to_type_arguments(ec, generic_args.clone())?, + generic_args_to_type_arguments(type_engine, ec, generic_args.clone())?, Some(generic_args.span()), ), None => (Vec::new(), None), @@ -1435,7 +1484,7 @@ fn expr_func_app_to_expression_kind( } let (type_arguments, type_arguments_span) = match generics_opt { Some((_double_colon_token, generic_args)) => ( - generic_args_to_type_arguments(ec, generic_args.clone())?, + generic_args_to_type_arguments(type_engine, ec, generic_args.clone())?, Some(generic_args.span()), ), None => (Vec::new(), None), @@ -1486,7 +1535,11 @@ fn expr_func_app_to_expression_kind( Ok(expression_kind) } -fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { +fn expr_to_expression( + type_engine: &TypeEngine, + ec: &mut ErrorContext, + expr: Expr, +) -> Result { let span = expr.span(); let expression = match expr { Expr::Path(path_expr) => path_expr_to_expression(ec, path_expr)?, @@ -1495,14 +1548,15 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let abi_cast_expression = abi_cast_args_to_abi_cast_expression(ec, args)?; + let abi_cast_expression = abi_cast_args_to_abi_cast_expression(type_engine, ec, args)?; Expression { kind: ExpressionKind::AbiCast(abi_cast_expression), span, } } Expr::Struct { path, fields } => { - let struct_expression = struct_path_and_fields_to_struct_expression(ec, path, fields)?; + let struct_expression = + struct_path_and_fields_to_struct_expression(type_engine, ec, path, fields)?; Expression { kind: ExpressionKind::Struct(struct_expression), span, @@ -1510,6 +1564,7 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { let fields = expr_tuple_descriptor_to_expressions( + type_engine, ec, parenthesized_expr_tuple_descriptor.into_inner(), )?; @@ -1518,16 +1573,16 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result expr_to_expression(ec, *parens.into_inner())?, + Expr::Parens(parens) => expr_to_expression(type_engine, ec, *parens.into_inner())?, Expr::Block(braced_code_block_contents) => { - braced_code_block_contents_to_expression(ec, braced_code_block_contents)? + braced_code_block_contents_to_expression(type_engine, ec, braced_code_block_contents)? } Expr::Array(bracketed_expr_array_descriptor) => { match bracketed_expr_array_descriptor.into_inner() { ExprArrayDescriptor::Sequence(exprs) => { let contents = exprs .into_iter() - .map(|expr| expr_to_expression(ec, expr)) + .map(|expr| expr_to_expression(type_engine, ec, expr)) .collect::>()?; Expression { kind: ExpressionKind::Array(contents), @@ -1535,7 +1590,7 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let expression = expr_to_expression(ec, *value)?; + let expression = expr_to_expression(type_engine, ec, *value)?; let length = expr_to_usize(ec, *length)?; let contents = iter::repeat_with(|| expression.clone()) .take(length) @@ -1548,7 +1603,7 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let asm_expression = asm_block_to_asm_expression(ec, asm_block)?; + let asm_expression = asm_block_to_asm_expression(type_engine, ec, asm_block)?; Expression { kind: ExpressionKind::Asm(asm_expression), span, @@ -1560,11 +1615,11 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result if_expr_to_expression(ec, if_expr)?, + Expr::If(if_expr) => if_expr_to_expression(type_engine, ec, if_expr)?, Expr::Match { value, branches, .. } => { - let value = expr_to_expression(ec, *value)?; + let value = expr_to_expression(type_engine, ec, *value)?; let var_decl_span = value.span(); // Generate a deterministic name for the variable returned by the match expression. @@ -1589,7 +1644,7 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result>()? }; Expression { @@ -1630,13 +1685,13 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let kind = expr_func_app_to_expression_kind(ec, func, args)?; + let kind = expr_func_app_to_expression_kind(type_engine, ec, func, args)?; Expression { kind, span } } Expr::Index { target, arg } => Expression { kind: ExpressionKind::ArrayIndex(ArrayIndexExpression { - prefix: Box::new(expr_to_expression(ec, *target)?), - index: Box::new(expr_to_expression(ec, *arg.into_inner())?), + prefix: Box::new(expr_to_expression(type_engine, ec, *target)?), + index: Box::new(expr_to_expression(type_engine, ec, *arg.into_inner())?), }), span, }, @@ -1649,6 +1704,7 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { let method_application_expression = method_call_fields_to_method_application_expression( + type_engine, ec, target, name, @@ -1695,7 +1751,7 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result Expression { kind: ExpressionKind::Subfield(SubfieldExpression { - prefix: Box::new(expr_to_expression(ec, *target)?), + prefix: Box::new(expr_to_expression(type_engine, ec, *target)?), field_to_access: name, }), span, @@ -1709,7 +1765,7 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result Expression { kind: ExpressionKind::TupleIndex(TupleIndexExpression { - prefix: Box::new(expr_to_expression(ec, *target)?), + prefix: Box::new(expr_to_expression(type_engine, ec, *target)?), index: match usize::try_from(field) { Ok(index) => index, Err(..) => { @@ -1722,18 +1778,22 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result unary_op_call(ec, "ref", ref_token.span(), span, *expr)?, + Expr::Ref { ref_token, expr } => { + unary_op_call(type_engine, ec, "ref", ref_token.span(), span, *expr)? + } Expr::Deref { deref_token, expr } => { - unary_op_call(ec, "deref", deref_token.span(), span, *expr)? + unary_op_call(type_engine, ec, "deref", deref_token.span(), span, *expr)? + } + Expr::Not { bang_token, expr } => { + unary_op_call(type_engine, ec, "not", bang_token.span(), span, *expr)? } - Expr::Not { bang_token, expr } => unary_op_call(ec, "not", bang_token.span(), span, *expr)?, Expr::Mul { lhs, star_token, rhs, } => { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("multiply", star_token.span(), span, lhs, rhs)? } Expr::Div { @@ -1741,8 +1801,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("divide", forward_slash_token.span(), span, lhs, rhs)? } Expr::Modulo { @@ -1750,8 +1810,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("modulo", percent_token.span(), span, lhs, rhs)? } Expr::Add { @@ -1759,8 +1819,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("add", add_token.span(), span, lhs, rhs)? } Expr::Sub { @@ -1768,8 +1828,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("subtract", sub_token.span(), span, lhs, rhs)? } Expr::Shl { @@ -1777,8 +1837,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("lsh", shl_token.span(), span, lhs, rhs)? } Expr::Shr { @@ -1786,8 +1846,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("rsh", shr_token.span(), span, lhs, rhs)? } Expr::BitAnd { @@ -1795,8 +1855,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("binary_and", ampersand_token.span(), span, lhs, rhs)? } Expr::BitXor { @@ -1804,8 +1864,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("binary_xor", caret_token.span(), span, lhs, rhs)? } Expr::BitOr { @@ -1813,8 +1873,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("binary_or", pipe_token.span(), span, lhs, rhs)? } Expr::Equal { @@ -1822,8 +1882,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("eq", double_eq_token.span(), span, lhs, rhs)? } Expr::NotEqual { @@ -1831,8 +1891,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("neq", bang_eq_token.span(), span, lhs, rhs)? } Expr::LessThan { @@ -1840,8 +1900,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("lt", less_than_token.span(), span, lhs, rhs)? } Expr::GreaterThan { @@ -1849,8 +1909,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("gt", greater_than_token.span(), span, lhs, rhs)? } Expr::LessThanEq { @@ -1858,8 +1918,8 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("le", less_than_eq_token.span(), span, lhs, rhs)? } Expr::GreaterThanEq { @@ -1867,23 +1927,23 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result { - let lhs = expr_to_expression(ec, *lhs)?; - let rhs = expr_to_expression(ec, *rhs)?; + let lhs = expr_to_expression(type_engine, ec, *lhs)?; + let rhs = expr_to_expression(type_engine, ec, *rhs)?; binary_op_call("ge", greater_than_eq_token.span(), span, lhs, rhs)? } Expr::LogicalAnd { lhs, rhs, .. } => Expression { kind: ExpressionKind::LazyOperator(LazyOperatorExpression { op: LazyOp::And, - lhs: Box::new(expr_to_expression(ec, *lhs)?), - rhs: Box::new(expr_to_expression(ec, *rhs)?), + lhs: Box::new(expr_to_expression(type_engine, ec, *lhs)?), + rhs: Box::new(expr_to_expression(type_engine, ec, *rhs)?), }), span, }, Expr::LogicalOr { lhs, rhs, .. } => Expression { kind: ExpressionKind::LazyOperator(LazyOperatorExpression { op: LazyOp::Or, - lhs: Box::new(expr_to_expression(ec, *lhs)?), - rhs: Box::new(expr_to_expression(ec, *rhs)?), + lhs: Box::new(expr_to_expression(type_engine, ec, *lhs)?), + rhs: Box::new(expr_to_expression(type_engine, ec, *rhs)?), }), span, }, @@ -1896,6 +1956,7 @@ fn expr_to_expression(ec: &mut ErrorContext, expr: Expr) -> Result Result { let storage_field = StorageField { name: storage_field.name, - type_info: ty_to_type_info(ec, storage_field.ty)?, - initializer: expr_to_expression(ec, storage_field.initializer)?, + type_info: ty_to_type_info(type_engine, ec, storage_field.ty)?, + initializer: expr_to_expression(type_engine, ec, storage_field.initializer)?, }; Ok(storage_field) } fn statement_to_ast_nodes( + type_engine: &TypeEngine, ec: &mut ErrorContext, statement: Statement, ) -> Result, ErrorEmitted> { let ast_nodes = match statement { - Statement::Let(statement_let) => statement_let_to_ast_nodes(ec, statement_let)?, - Statement::Item(item) => item_to_ast_nodes(ec, item)?, - Statement::Expr { expr, .. } => vec![expr_to_ast_node(ec, expr, true)?], + Statement::Let(statement_let) => { + statement_let_to_ast_nodes(type_engine, ec, statement_let)? + } + Statement::Item(item) => item_to_ast_nodes(type_engine, ec, item)?, + Statement::Expr { expr, .. } => vec![expr_to_ast_node(type_engine, ec, expr, true)?], }; Ok(ast_nodes) } fn fn_arg_to_function_parameter( + type_engine: &TypeEngine, ec: &mut ErrorContext, fn_arg: FnArg, ) -> Result { @@ -2023,7 +2089,7 @@ fn fn_arg_to_function_parameter( let function_parameter = FunctionParameter { name, is_mutable: false, - type_id: insert_type(ty_to_type_info(ec, fn_arg.ty)?), + type_id: type_engine.insert_type(ty_to_type_info(type_engine, ec, fn_arg.ty)?), type_span, }; Ok(function_parameter) @@ -2163,6 +2229,7 @@ fn path_type_segment_to_ident( /// Similar to [path_type_segment_to_ident], but allows for the item to be either /// type arguments _or_ an ident. fn path_expr_segment_to_ident_or_type_argument( + type_engine: &TypeEngine, ec: &mut ErrorContext, path_expr_segment: PathExprSegment, ) -> Result<(Ident, Vec), ErrorEmitted> { @@ -2179,7 +2246,7 @@ fn path_expr_segment_to_ident_or_type_argument( } let generic_args = generics_opt.map(|(_, y)| y); let type_args = match generic_args { - Some(x) => generic_args_to_type_arguments(ec, x)?, + Some(x) => generic_args_to_type_arguments(type_engine, ec, x)?, None => Default::default(), }; Ok((name, type_args)) @@ -2239,11 +2306,13 @@ fn path_expr_to_expression( } fn braced_code_block_contents_to_expression( + type_engine: &TypeEngine, ec: &mut ErrorContext, braced_code_block_contents: Braces, ) -> Result { let span = braced_code_block_contents.span(); - let code_block = braced_code_block_contents_to_code_block(ec, braced_code_block_contents)?; + let code_block = + braced_code_block_contents_to_code_block(type_engine, ec, braced_code_block_contents)?; Ok(Expression { kind: ExpressionKind::CodeBlock(code_block), span, @@ -2251,6 +2320,7 @@ fn braced_code_block_contents_to_expression( } fn if_expr_to_expression( + type_engine: &TypeEngine, ec: &mut ErrorContext, if_expr: IfExpr, ) -> Result { @@ -2263,7 +2333,11 @@ fn if_expr_to_expression( } = if_expr; let then_block_span = then_block.span(); let then_block = Expression { - kind: ExpressionKind::CodeBlock(braced_code_block_contents_to_code_block(ec, then_block)?), + kind: ExpressionKind::CodeBlock(braced_code_block_contents_to_code_block( + type_engine, + ec, + then_block, + )?), span: then_block_span.clone(), }; let else_block = match else_opt { @@ -2271,9 +2345,13 @@ fn if_expr_to_expression( Some((_else_token, tail)) => { let expression = match tail { ControlFlow::Break(braced_code_block_contents) => { - braced_code_block_contents_to_expression(ec, braced_code_block_contents)? + braced_code_block_contents_to_expression( + type_engine, + ec, + braced_code_block_contents, + )? } - ControlFlow::Continue(if_expr) => if_expr_to_expression(ec, *if_expr)?, + ControlFlow::Continue(if_expr) => if_expr_to_expression(type_engine, ec, *if_expr)?, }; Some(expression) } @@ -2281,14 +2359,14 @@ fn if_expr_to_expression( let expression = match condition { IfCondition::Expr(condition) => Expression { kind: ExpressionKind::If(IfExpression { - condition: Box::new(expr_to_expression(ec, *condition)?), + condition: Box::new(expr_to_expression(type_engine, ec, *condition)?), then: Box::new(then_block), r#else: else_block.map(Box::new), }), span, }, IfCondition::Let { lhs, rhs, .. } => { - let scrutinee = pattern_to_scrutinee(ec, *lhs)?; + let scrutinee = pattern_to_scrutinee(type_engine, ec, *lhs)?; let scrutinee_span = scrutinee.span(); let mut branches = vec![MatchBranch { scrutinee, @@ -2327,7 +2405,7 @@ fn if_expr_to_expression( }); Expression { kind: ExpressionKind::Match(MatchExpression { - value: Box::new(expr_to_expression(ec, *rhs)?), + value: Box::new(expr_to_expression(type_engine, ec, *rhs)?), branches, }), span, @@ -2482,6 +2560,7 @@ fn literal_to_literal( /// Use this when converting a call path that could potentially include type arguments, i.e. the /// turbofish. fn path_expr_to_call_path_binding( + type_engine: &TypeEngine, ec: &mut ErrorContext, path_expr: PathExpr, ) -> Result>, ErrorEmitted> { @@ -2501,7 +2580,7 @@ fn path_expr_to_call_path_binding( prefixes.push(ident); } let (suffix, ty_args) = - path_expr_segment_to_ident_or_type_argument(ec, call_path_suffix)?; + path_expr_segment_to_ident_or_type_argument(type_engine, ec, call_path_suffix)?; let type_info_span = suffix.span(); let type_info = type_name_to_type_info_opt(&suffix).unwrap_or(TypeInfo::Custom { name: suffix, @@ -2510,7 +2589,8 @@ fn path_expr_to_call_path_binding( (prefixes, type_info, type_info_span, ty_args) } None => { - let (suffix, ty_args) = path_expr_segment_to_ident_or_type_argument(ec, prefix)?; + let (suffix, ty_args) = + path_expr_segment_to_ident_or_type_argument(type_engine, ec, prefix)?; let type_info_span = suffix.span(); let type_info = match type_name_to_type_info_opt(&suffix) { Some(type_info) => type_info, @@ -2566,12 +2646,13 @@ fn path_expr_to_call_path( } fn expr_struct_field_to_struct_expression_field( + type_engine: &TypeEngine, ec: &mut ErrorContext, expr_struct_field: ExprStructField, ) -> Result { let span = expr_struct_field.span(); let value = match expr_struct_field.expr_opt { - Some((_colon_token, expr)) => expr_to_expression(ec, *expr)?, + Some((_colon_token, expr)) => expr_to_expression(type_engine, ec, *expr)?, None => Expression { kind: ExpressionKind::Variable(expr_struct_field.field_name.clone()), span: span.clone(), @@ -2585,15 +2666,16 @@ fn expr_struct_field_to_struct_expression_field( } fn expr_tuple_descriptor_to_expressions( + type_engine: &TypeEngine, ec: &mut ErrorContext, expr_tuple_descriptor: ExprTupleDescriptor, ) -> Result, ErrorEmitted> { let expressions = match expr_tuple_descriptor { ExprTupleDescriptor::Nil => Vec::new(), ExprTupleDescriptor::Cons { head, tail, .. } => { - let mut expressions = vec![expr_to_expression(ec, *head)?]; + let mut expressions = vec![expr_to_expression(type_engine, ec, *head)?]; for expr in tail { - expressions.push(expr_to_expression(ec, expr)?); + expressions.push(expr_to_expression(type_engine, ec, expr)?); } expressions } @@ -2602,6 +2684,7 @@ fn expr_tuple_descriptor_to_expressions( } fn asm_block_to_asm_expression( + type_engine: &TypeEngine, ec: &mut ErrorContext, asm_block: AsmBlock, ) -> Result, ErrorEmitted> { @@ -2614,7 +2697,7 @@ fn asm_block_to_asm_expression( }; let returns = Some((asm_register, asm_final_expr.register.span())); let return_type = match asm_final_expr.ty_opt { - Some((_colon_token, ty)) => ty_to_type_info(ec, ty)?, + Some((_colon_token, ty)) => ty_to_type_info(type_engine, ec, ty)?, None => TypeInfo::UnsignedInteger(IntegerBits::SixtyFour), }; (returns, return_type) @@ -2627,7 +2710,11 @@ fn asm_block_to_asm_expression( .into_inner() .into_iter() .map(|asm_register_declaration| { - asm_register_declaration_to_asm_register_declaration(ec, asm_register_declaration) + asm_register_declaration_to_asm_register_declaration( + type_engine, + ec, + asm_register_declaration, + ) }) .collect::>()? }; @@ -2648,33 +2735,38 @@ fn asm_block_to_asm_expression( } fn match_branch_to_match_branch( + type_engine: &TypeEngine, ec: &mut ErrorContext, match_branch: sway_ast::MatchBranch, ) -> Result { let span = match_branch.span(); Ok(MatchBranch { - scrutinee: pattern_to_scrutinee(ec, match_branch.pattern)?, + scrutinee: pattern_to_scrutinee(type_engine, ec, match_branch.pattern)?, result: match match_branch.kind { MatchBranchKind::Block { block, .. } => { let span = block.span(); Expression { kind: ExpressionKind::CodeBlock(braced_code_block_contents_to_code_block( - ec, block, + type_engine, + ec, + block, )?), span, } } - MatchBranchKind::Expr { expr, .. } => expr_to_expression(ec, expr)?, + MatchBranchKind::Expr { expr, .. } => expr_to_expression(type_engine, ec, expr)?, }, span, }) } fn statement_let_to_ast_nodes( + type_engine: &TypeEngine, ec: &mut ErrorContext, statement_let: StatementLet, ) -> Result, ErrorEmitted> { fn unfold( + type_engine: &TypeEngine, ec: &mut ErrorContext, pattern: Pattern, ty_opt: Option, @@ -2691,7 +2783,7 @@ fn statement_let_to_ast_nodes( let (type_ascription, type_ascription_span) = match ty_opt { Some(ty) => { let type_ascription_span = ty.span(); - let type_ascription = ty_to_type_info(ec, ty)?; + let type_ascription = ty_to_type_info(type_engine, ec, ty)?; (type_ascription, Some(type_ascription_span)) } None => (TypeInfo::Unknown, None), @@ -2745,7 +2837,7 @@ fn statement_let_to_ast_nodes( let (type_ascription, type_ascription_span) = match &ty_opt { Some(ty) => { let type_ascription_span = ty.span(); - let type_ascription = ty_to_type_info(ec, ty.clone())?; + let type_ascription = ty_to_type_info(type_engine, ec, ty.clone())?; (type_ascription, Some(type_ascription_span)) } None => (TypeInfo::Unknown, None), @@ -2797,6 +2889,7 @@ fn statement_let_to_ast_nodes( // recursively create variable declarations for the subpatterns on the LHS // and add them to the ast nodes ast_nodes.extend(unfold( + type_engine, ec, recursive_pattern, None, @@ -2833,7 +2926,7 @@ fn statement_let_to_ast_nodes( let (type_ascription, type_ascription_span) = match &ty_opt { Some(ty) => { let type_ascription_span = ty.span(); - let type_ascription = ty_to_type_info(ec, ty.clone())?; + let type_ascription = ty_to_type_info(type_engine, ec, ty.clone())?; (type_ascription, Some(type_ascription_span)) } None => (TypeInfo::Unknown, None), @@ -2879,6 +2972,7 @@ fn statement_let_to_ast_nodes( // recursively create variable declarations for the subpatterns on the LHS // and add them to the ast nodes ast_nodes.extend(unfold( + type_engine, ec, pattern, ty_opt, @@ -2899,8 +2993,9 @@ fn statement_let_to_ast_nodes( Ok(ast_nodes) } let span = statement_let.span(); - let initial_expression = expr_to_expression(ec, statement_let.expr)?; + let initial_expression = expr_to_expression(type_engine, ec, statement_let.expr)?; unfold( + type_engine, ec, statement_let.pattern, statement_let.ty_opt.map(|(_colon_token, ty)| ty), @@ -2919,6 +3014,7 @@ fn dependency_to_include_statement(dependency: &Dependency) -> IncludeStatement #[allow(dead_code)] fn generic_args_to_type_parameters( + type_engine: &TypeEngine, ec: &mut ErrorContext, generic_args: GenericArgs, ) -> Result, ErrorEmitted> { @@ -2926,11 +3022,12 @@ fn generic_args_to_type_parameters( .parameters .into_inner() .into_iter() - .map(|x| ty_to_type_parameter(ec, x)) + .map(|x| ty_to_type_parameter(type_engine, ec, x)) .collect() } fn asm_register_declaration_to_asm_register_declaration( + type_engine: &TypeEngine, ec: &mut ErrorContext, asm_register_declaration: sway_ast::AsmRegisterDeclaration, ) -> Result { @@ -2938,7 +3035,7 @@ fn asm_register_declaration_to_asm_register_declaration( name: asm_register_declaration.register, initializer: asm_register_declaration .value_opt - .map(|(_colon_token, expr)| expr_to_expression(ec, *expr)) + .map(|(_colon_token, expr)| expr_to_expression(type_engine, ec, *expr)) .transpose()?, }) } @@ -2953,6 +3050,7 @@ fn instruction_to_asm_op(instruction: Instruction) -> AsmOp { } fn pattern_to_scrutinee( + type_engine: &TypeEngine, ec: &mut ErrorContext, pattern: Pattern, ) -> Result { @@ -2987,7 +3085,7 @@ fn pattern_to_scrutinee( }; Scrutinee::EnumScrutinee { call_path: path_expr_to_call_path(ec, path)?, - value: Box::new(pattern_to_scrutinee(ec, value)?), + value: Box::new(pattern_to_scrutinee(type_engine, ec, value)?), span, } } @@ -3018,7 +3116,7 @@ fn pattern_to_scrutinee( let scrutinee_fields = fields .into_iter() - .map(|field| pattern_struct_field_to_struct_scrutinee_field(ec, field)) + .map(|field| pattern_struct_field_to_struct_scrutinee_field(type_engine, ec, field)) .collect::>()?; Scrutinee::StructScrutinee { @@ -3032,7 +3130,7 @@ fn pattern_to_scrutinee( pat_tuple .into_inner() .into_iter() - .map(|pattern| pattern_to_scrutinee(ec, pattern)) + .map(|pattern| pattern_to_scrutinee(type_engine, ec, pattern)) .collect::>()? }, span, @@ -3042,12 +3140,16 @@ fn pattern_to_scrutinee( } #[allow(dead_code)] -fn ty_to_type_parameter(ec: &mut ErrorContext, ty: Ty) -> Result { +fn ty_to_type_parameter( + type_engine: &TypeEngine, + ec: &mut ErrorContext, + ty: Ty, +) -> Result { let name_ident = match ty { Ty::Path(path_type) => path_type_to_ident(ec, path_type)?, Ty::Infer { underscore_token } => { return Ok(TypeParameter { - type_id: insert_type(TypeInfo::Unknown), + type_id: type_engine.insert_type(TypeInfo::Unknown), name_ident: underscore_token.into(), trait_constraints: Default::default(), }) @@ -3057,7 +3159,7 @@ fn ty_to_type_parameter(ec: &mut ErrorContext, ty: Ty) -> Result panic!("str types are not allowed in this position"), }; Ok(TypeParameter { - type_id: insert_type(TypeInfo::Custom { + type_id: type_engine.insert_type(TypeInfo::Custom { name: name_ident.clone(), type_arguments: None, }), @@ -3094,6 +3196,7 @@ fn path_expr_to_ident(ec: &mut ErrorContext, path_expr: PathExpr) -> Result Result { @@ -3110,7 +3213,7 @@ fn pattern_struct_field_to_struct_scrutinee_field( let struct_scrutinee_field = StructScrutineeField::Field { field: field_name, scrutinee: pattern_opt - .map(|(_colon_token, pattern)| pattern_to_scrutinee(ec, *pattern)) + .map(|(_colon_token, pattern)| pattern_to_scrutinee(type_engine, ec, *pattern)) .transpose()?, span, }; @@ -3120,6 +3223,7 @@ fn pattern_struct_field_to_struct_scrutinee_field( } fn assignable_to_expression( + type_engine: &TypeEngine, ec: &mut ErrorContext, assignable: Assignable, ) -> Result { @@ -3131,8 +3235,8 @@ fn assignable_to_expression( }, Assignable::Index { target, arg } => Expression { kind: ExpressionKind::ArrayIndex(ArrayIndexExpression { - prefix: Box::new(assignable_to_expression(ec, *target)?), - index: Box::new(expr_to_expression(ec, *arg.into_inner())?), + prefix: Box::new(assignable_to_expression(type_engine, ec, *target)?), + index: Box::new(expr_to_expression(type_engine, ec, *arg.into_inner())?), }), span, }, @@ -3166,7 +3270,7 @@ fn assignable_to_expression( } None => Expression { kind: ExpressionKind::Subfield(SubfieldExpression { - prefix: Box::new(assignable_to_expression(ec, *target)?), + prefix: Box::new(assignable_to_expression(type_engine, ec, *target)?), field_to_access: name, }), span, @@ -3188,7 +3292,7 @@ fn assignable_to_expression( }; Expression { kind: ExpressionKind::TupleIndex(TupleIndexExpression { - prefix: Box::new(assignable_to_expression(ec, *target)?), + prefix: Box::new(assignable_to_expression(type_engine, ec, *target)?), index, index_span: field_span, }), @@ -3200,6 +3304,7 @@ fn assignable_to_expression( } fn assignable_to_reassignment_target( + type_engine: &TypeEngine, ec: &mut ErrorContext, assignable: Assignable, ) -> Result { @@ -3222,11 +3327,12 @@ fn assignable_to_reassignment_target( Assignable::TupleFieldProjection { .. } => break, } } - let expression = assignable_to_expression(ec, assignable)?; + let expression = assignable_to_expression(type_engine, ec, assignable)?; Ok(ReassignmentTarget::VariableExpression(Box::new(expression))) } fn generic_args_to_type_arguments( + type_engine: &TypeEngine, ec: &mut ErrorContext, generic_args: GenericArgs, ) -> Result, ErrorEmitted> { @@ -3236,22 +3342,23 @@ fn generic_args_to_type_arguments( .into_iter() .map(|ty| { let span = ty.span(); - let type_id = insert_type(ty_to_type_info(ec, ty)?); + let type_id = type_engine.insert_type(ty_to_type_info(type_engine, ec, ty)?); Ok(TypeArgument { type_id, span }) }) .collect() } fn ty_tuple_descriptor_to_type_arguments( + type_engine: &TypeEngine, ec: &mut ErrorContext, ty_tuple_descriptor: TyTupleDescriptor, ) -> Result, ErrorEmitted> { let type_arguments = match ty_tuple_descriptor { TyTupleDescriptor::Nil => vec![], TyTupleDescriptor::Cons { head, tail, .. } => { - let mut type_arguments = vec![ty_to_type_argument(ec, *head)?]; + let mut type_arguments = vec![ty_to_type_argument(type_engine, ec, *head)?]; for ty in tail.into_iter() { - type_arguments.push(ty_to_type_argument(ec, ty)?); + type_arguments.push(ty_to_type_argument(type_engine, ec, ty)?); } type_arguments } @@ -3260,6 +3367,7 @@ fn ty_tuple_descriptor_to_type_arguments( } fn path_type_to_type_info( + type_engine: &TypeEngine, ec: &mut ErrorContext, path_type: PathType, ) -> Result { @@ -3326,7 +3434,7 @@ fn path_type_to_type_info( } else { let type_arguments = match generics_opt { Some((_double_colon_token, generic_args)) => { - generic_args_to_type_arguments(ec, generic_args)? + generic_args_to_type_arguments(type_engine, ec, generic_args)? } None => Vec::new(), }; diff --git a/sway-core/src/lib.rs b/sway-core/src/lib.rs index 0e37d6261e6..96cbc2563e6 100644 --- a/sway-core/src/lib.rs +++ b/sway-core/src/lib.rs @@ -24,6 +24,7 @@ use control_flow_analysis::ControlFlowGraph; use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::sync::Arc; +use type_system::TypeEngine; pub use semantic_analysis::{ namespace::{self, Namespace}, @@ -51,20 +52,24 @@ pub use type_system::TypeInfo; /// /// # Panics /// Panics if the parser panics. -pub fn parse(input: Arc, config: Option<&BuildConfig>) -> CompileResult { +pub fn parse( + input: Arc, + config: Option<&BuildConfig>, + type_engine: &TypeEngine, +) -> CompileResult { match config { - None => parse_in_memory(input), - Some(config) => parse_files(input, config), + None => parse_in_memory(input, type_engine), + Some(config) => parse_files(input, config, type_engine), } } /// When no `BuildConfig` is given, we're assumed to be parsing in-memory with no submodules. -fn parse_in_memory(src: Arc) -> CompileResult { +fn parse_in_memory(src: Arc, type_engine: &TypeEngine) -> CompileResult { let module = match sway_parse::parse_file(src, None) { Ok(module) => module, Err(error) => return err(vec![], parse_file_error_to_compile_errors(error)), }; - convert_parse_tree::convert_parse_tree(module).flat_map(|(kind, tree)| { + convert_parse_tree::convert_parse_tree(module, type_engine).flat_map(|(kind, tree)| { let submodules = Default::default(); let root = ParseModule { tree, submodules }; let program = ParseProgram { kind, root }; @@ -74,9 +79,13 @@ fn parse_in_memory(src: Arc) -> CompileResult { /// When a `BuildConfig` is given, the module source may declare `dep`s that must be parsed from /// other files. -fn parse_files(src: Arc, config: &BuildConfig) -> CompileResult { +fn parse_files( + src: Arc, + config: &BuildConfig, + type_engine: &TypeEngine, +) -> CompileResult { let root_mod_path = config.canonical_root_module(); - parse_module_tree(src, root_mod_path).flat_map(|(kind, root)| { + parse_module_tree(src, root_mod_path, type_engine).flat_map(|(kind, root)| { let program = ParseProgram { kind, root }; ok(program, vec![], vec![]) }) @@ -84,7 +93,11 @@ fn parse_files(src: Arc, config: &BuildConfig) -> CompileResult, path: Arc) -> CompileResult<(TreeType, ParseModule)> { +fn parse_module_tree( + src: Arc, + path: Arc, + type_engine: &TypeEngine, +) -> CompileResult<(TreeType, ParseModule)> { // Parse this module first. let module = match sway_parse::parse_file(src, Some(path.clone())) { Ok(module) => module, @@ -107,33 +120,35 @@ fn parse_module_tree(src: Arc, path: Arc) -> CompileResult<(TreeTy return res.flat_map(|_| err(vec![], vec![error])); } }; - parse_module_tree(dep_str.clone(), dep_path.clone()).flat_map(|(kind, module)| { - let library_name = match kind { - TreeType::Library { name } => name, - _ => { - let span = span::Span::new(dep_str, 0, 0, Some(dep_path)).unwrap(); - let error = CompileError::ImportMustBeLibrary { span }; - return err(vec![], vec![error]); - } - }; - // NOTE: Typed `IncludStatement`'s include an `alias` field, however its only - // constructor site is always `None`. If we introduce dep aliases in the future, this - // is where we should use it. - let dep_alias = None; - let dep_name = dep_alias.unwrap_or_else(|| library_name.clone()); - let submodule = ParseSubmodule { - library_name, - module, - }; - res.flat_map(|mut submods| { - submods.push((dep_name, submodule)); - ok(submods, vec![], vec![]) - }) - }) + parse_module_tree(dep_str.clone(), dep_path.clone(), type_engine).flat_map( + |(kind, module)| { + let library_name = match kind { + TreeType::Library { name } => name, + _ => { + let span = span::Span::new(dep_str, 0, 0, Some(dep_path)).unwrap(); + let error = CompileError::ImportMustBeLibrary { span }; + return err(vec![], vec![error]); + } + }; + // NOTE: Typed `IncludStatement`'s include an `alias` field, however its only + // constructor site is always `None`. If we introduce dep aliases in the future, this + // is where we should use it. + let dep_alias = None; + let dep_name = dep_alias.unwrap_or_else(|| library_name.clone()); + let submodule = ParseSubmodule { + library_name, + module, + }; + res.flat_map(|mut submods| { + submods.push((dep_name, submodule)); + ok(submods, vec![], vec![]) + }) + }, + ) }); // Convert from the raw parsed module to the `ParseTree` ready for type-check. - convert_parse_tree::convert_parse_tree(module).flat_map(|(prog_kind, tree)| { + convert_parse_tree::convert_parse_tree(module, type_engine).flat_map(|(prog_kind, tree)| { submodules_res.flat_map(|submodules| { let parse_module = ParseModule { tree, submodules }; ok((prog_kind, parse_module), vec![], vec![]) @@ -207,6 +222,7 @@ pub enum BytecodeCompilationResult { pub fn parsed_to_ast( parse_program: &ParseProgram, initial_namespace: namespace::Module, + initial_type_engine: &type_system::TypeEngine, ) -> CompileAstResult { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -215,7 +231,7 @@ pub fn parsed_to_ast( value: typed_program_result, warnings: new_warnings, errors: new_errors, - } = TypedProgram::type_check(parse_program, initial_namespace); + } = TypedProgram::type_check(parse_program, initial_namespace, initial_type_engine); warnings.extend(new_warnings); errors.extend(new_errors); let typed_program = match typed_program_result { @@ -268,11 +284,13 @@ pub fn compile_to_ast( let mut warnings = Vec::new(); let mut errors = Vec::new(); + let type_engine = TypeEngine::default(); + let CompileResult { value: parse_program_opt, warnings: new_warnings, errors: new_errors, - } = parse(input, build_config); + } = parse(input, build_config, &type_engine); warnings.extend(new_warnings); errors.extend(new_errors); @@ -285,7 +303,7 @@ pub fn compile_to_ast( } }; - match parsed_to_ast(&parse_program, initial_namespace) { + match parsed_to_ast(&parse_program, initial_namespace, &type_engine) { CompileAstResult::Success { typed_program, warnings: new_warnings, @@ -597,10 +615,10 @@ fn module_return_path_analysis(module: &TypedModule, errors: &mut Vec where @@ -609,7 +627,6 @@ fn test_basic_prog() { x: u32, y: MyStruct } - enum MyOtherSumType { x: u32, @@ -619,8 +636,6 @@ fn test_basic_prog() { field_name: u64, other_field: T, } - - fn generic_function (arg1: u64, @@ -644,15 +659,10 @@ fn test_basic_prog() { _ => { return false; }, }; } - struct MyStruct { test: string, } - - - use stdlib::println; - trait MyTrait { // interface points fn myfunc(x: int) -> unit; @@ -665,7 +675,6 @@ fn test_basic_prog() { self.interface_fn(x); } } - pub fn prints_number_five() -> u8 { let x: u8 = 5; let reference_to_x = ref x; @@ -681,6 +690,7 @@ fn test_basic_prog() { "# .into(), None, + &type_engine, ); let mut warnings: Vec = Vec::new(); let mut errors: Vec = Vec::new(); @@ -688,6 +698,7 @@ fn test_basic_prog() { } #[test] fn test_parenthesized() { + let type_engine = TypeEngine::default(); let prog = parse( r#" contract; @@ -698,6 +709,7 @@ fn test_parenthesized() { "# .into(), None, + &type_engine, ); let mut warnings: Vec = Vec::new(); let mut errors: Vec = Vec::new(); @@ -707,6 +719,7 @@ fn test_parenthesized() { #[test] fn test_unary_ordering() { use crate::parse_tree::declaration::FunctionDeclaration; + let type_engine = TypeEngine::default(); let prog = parse( r#" script; @@ -717,6 +730,7 @@ fn test_unary_ordering() { }"# .into(), None, + &type_engine, ); let mut warnings: Vec = Vec::new(); let mut errors: Vec = Vec::new(); 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 bcc8caf34c8..8c6c3b7e633 100644 --- a/sway-core/src/semantic_analysis/ast_node/code_block.rs +++ b/sway-core/src/semantic_analysis/ast_node/code_block.rs @@ -7,10 +7,10 @@ pub struct TypedCodeBlock { } impl CopyTypes for TypedCodeBlock { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { self.contents .iter_mut() - .for_each(|x| x.copy_types(type_mapping)); + .for_each(|x| x.copy_types(type_engine, type_mapping)); } } @@ -23,6 +23,7 @@ impl DeterministicallyAborts for TypedCodeBlock { impl TypedCodeBlock { pub(crate) fn type_check( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, code_block: CodeBlock, ) -> CompileResult<(Self, TypeId)> { let mut warnings = Vec::new(); @@ -35,7 +36,8 @@ impl TypedCodeBlock { .iter() .filter_map(|node| { let ctx = ctx.by_ref().scoped(&mut code_block_namespace); - TypedAstNode::type_check(ctx, node.clone()).ok(&mut warnings, &mut errors) + TypedAstNode::type_check(ctx, type_engine, node.clone()) + .ok(&mut warnings, &mut errors) }) .collect::>(); @@ -73,7 +75,8 @@ impl TypedCodeBlock { let typed_code_block = TypedCodeBlock { contents: evaluated_contents, }; - let type_id = return_type.unwrap_or_else(|| insert_type(TypeInfo::Tuple(Vec::new()))); + let type_id = + return_type.unwrap_or_else(|| type_engine.insert_type(TypeInfo::Tuple(Vec::new()))); ok((typed_code_block, type_id), warnings, errors) } } diff --git a/sway-core/src/semantic_analysis/ast_node/declaration.rs b/sway-core/src/semantic_analysis/ast_node/declaration.rs index 65c7637010a..17401b809fd 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration.rs @@ -45,17 +45,25 @@ pub enum TypedDeclaration { impl CopyTypes for TypedDeclaration { /// The entry point to monomorphizing typed declarations. Instantiates all new type ids, /// assuming `self` has already been copied. - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { use TypedDeclaration::*; match self { - VariableDeclaration(ref mut var_decl) => var_decl.copy_types(type_mapping), - ConstantDeclaration(ref mut const_decl) => const_decl.copy_types(type_mapping), - FunctionDeclaration(ref mut fn_decl) => fn_decl.copy_types(type_mapping), - TraitDeclaration(ref mut trait_decl) => trait_decl.copy_types(type_mapping), - StructDeclaration(ref mut struct_decl) => struct_decl.copy_types(type_mapping), - EnumDeclaration(ref mut enum_decl) => enum_decl.copy_types(type_mapping), - Reassignment(ref mut reassignment) => reassignment.copy_types(type_mapping), - ImplTrait(impl_trait) => impl_trait.copy_types(type_mapping), + VariableDeclaration(ref mut var_decl) => var_decl.copy_types(type_engine, type_mapping), + ConstantDeclaration(ref mut const_decl) => { + const_decl.copy_types(type_engine, type_mapping) + } + FunctionDeclaration(ref mut fn_decl) => fn_decl.copy_types(type_engine, type_mapping), + TraitDeclaration(ref mut trait_decl) => { + trait_decl.copy_types(type_engine, type_mapping) + } + StructDeclaration(ref mut struct_decl) => { + struct_decl.copy_types(type_engine, type_mapping) + } + EnumDeclaration(ref mut enum_decl) => enum_decl.copy_types(type_engine, type_mapping), + Reassignment(ref mut reassignment) => { + reassignment.copy_types(type_engine, type_mapping) + } + ImplTrait(impl_trait) => impl_trait.copy_types(type_engine, type_mapping), // generics in an ABI is unsupported by design AbiDeclaration(..) | StorageDeclaration(..) @@ -327,7 +335,7 @@ impl TypedDeclaration { } } - pub(crate) fn return_type(&self) -> CompileResult { + pub(crate) fn return_type(&self, type_engine: &TypeEngine) -> CompileResult { let type_id = match self { TypedDeclaration::VariableDeclaration(TypedVariableDeclaration { body, .. }) => { body.return_type @@ -341,14 +349,16 @@ impl TypedDeclaration { )], ) } - TypedDeclaration::StructDeclaration(decl) => decl.create_type_id(), - TypedDeclaration::EnumDeclaration(decl) => decl.create_type_id(), + TypedDeclaration::StructDeclaration(decl) => decl.create_type_id(type_engine), + TypedDeclaration::EnumDeclaration(decl) => decl.create_type_id(type_engine), TypedDeclaration::Reassignment(TypedReassignment { rhs, .. }) => rhs.return_type, - TypedDeclaration::StorageDeclaration(decl) => insert_type(TypeInfo::Storage { - fields: decl.fields_as_typed_struct_fields(), - }), + TypedDeclaration::StorageDeclaration(decl) => { + type_engine.insert_type(TypeInfo::Storage { + fields: decl.fields_as_typed_struct_fields(), + }) + } TypedDeclaration::GenericTypeForFunctionScope { name, type_id } => { - insert_type(TypeInfo::Ref(*type_id, name.span())) + type_engine.insert_type(TypeInfo::Ref(*type_id, name.span())) } decl => { return err( @@ -396,8 +406,8 @@ pub struct TypedConstantDeclaration { } impl CopyTypes for TypedConstantDeclaration { - fn copy_types(&mut self, type_mapping: &TypeMapping) { - self.value.copy_types(type_mapping); + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { + self.value.copy_types(type_engine, type_mapping); } } @@ -414,9 +424,9 @@ pub struct TypedTraitFn { } impl CopyTypes for TypedTraitFn { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { self.return_type - .update_type(type_mapping, &self.return_type_span); + .update_type(type_engine, type_mapping, &self.return_type_span); } } @@ -493,9 +503,9 @@ pub struct TypedReassignment { } impl CopyTypes for TypedReassignment { - fn copy_types(&mut self, type_mapping: &TypeMapping) { - self.rhs.copy_types(type_mapping); + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { + self.rhs.copy_types(type_engine, type_mapping); self.lhs_type - .update_type(type_mapping, &self.lhs_base_name.span()); + .update_type(type_engine, type_mapping, &self.lhs_base_name.span()); } } diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs b/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs index dd824b8c092..65961183737 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/abi.rs @@ -7,7 +7,7 @@ use crate::{ ast_node::{type_check_interface_surface, type_check_trait_methods}, TypeCheckContext, }, - type_system::{insert_type, AbiName, TypeId}, + type_system::{AbiName, TypeEngine, TypeId}, AbiDeclaration, CompileResult, FunctionDeclaration, TypeInfo, }; @@ -32,18 +32,19 @@ pub struct TypedAbiDeclaration { } impl CreateTypeId for TypedAbiDeclaration { - fn create_type_id(&self) -> TypeId { + fn create_type_id(&self, type_engine: &TypeEngine) -> TypeId { let ty = TypeInfo::ContractCaller { abi_name: AbiName::Known(self.name.clone().into()), address: None, }; - insert_type(ty) + type_engine.insert_type(ty) } } impl TypedAbiDeclaration { pub(crate) fn type_check( ctx: TypeCheckContext, + type_engine: &TypeEngine, abi_decl: AbiDeclaration, ) -> CompileResult { let mut warnings = vec![]; @@ -62,7 +63,7 @@ impl TypedAbiDeclaration { // so we don't support the case of calling a contract's own interface // from itself. This is by design. let interface_surface = check!( - type_check_interface_surface(interface_surface, ctx.namespace), + type_check_interface_surface(type_engine, interface_surface, ctx.namespace), return err(warnings, errors), warnings, errors @@ -70,7 +71,7 @@ impl TypedAbiDeclaration { // type check these for errors but don't actually use them yet -- the real // ones will be type checked with proper symbols when the ABI is implemented let _methods = check!( - type_check_trait_methods(ctx, methods.clone()), + type_check_trait_methods(ctx, type_engine, methods.clone()), vec![], warnings, errors diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs b/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs index b0f9185f4bb..dab029008eb 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/enum.rs @@ -3,8 +3,8 @@ use crate::{ parse_tree::*, semantic_analysis::*, type_system::{ - insert_type, look_up_type_id, CopyTypes, CreateTypeId, EnforceTypeArguments, - MonomorphizeHelper, ReplaceSelfType, TypeId, TypeMapping, TypeParameter, + look_up_type_id, CopyTypes, CreateTypeId, EnforceTypeArguments, MonomorphizeHelper, + ReplaceSelfType, TypeEngine, TypeId, TypeMapping, TypeParameter, }, types::{JsonAbiString, ToJsonAbi}, TypeInfo, @@ -34,19 +34,19 @@ impl PartialEq for TypedEnumDeclaration { } impl CopyTypes for TypedEnumDeclaration { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { self.variants .iter_mut() - .for_each(|x| x.copy_types(type_mapping)); + .for_each(|x| x.copy_types(type_engine, type_mapping)); self.type_parameters .iter_mut() - .for_each(|x| x.copy_types(type_mapping)); + .for_each(|x| x.copy_types(type_engine, type_mapping)); } } impl CreateTypeId for TypedEnumDeclaration { - fn create_type_id(&self) -> TypeId { - insert_type(TypeInfo::Enum { + fn create_type_id(&self, type_engine: &TypeEngine) -> TypeId { + type_engine.insert_type(TypeInfo::Enum { name: self.name.clone(), variant_types: self.variants.clone(), type_parameters: self.type_parameters.clone(), @@ -71,7 +71,11 @@ impl MonomorphizeHelper for TypedEnumDeclaration { } impl TypedEnumDeclaration { - pub fn type_check(ctx: TypeCheckContext, decl: EnumDeclaration) -> CompileResult { + pub fn type_check( + ctx: TypeCheckContext, + type_engine: &TypeEngine, + decl: EnumDeclaration, + ) -> CompileResult { let mut errors = vec![]; let mut warnings = vec![]; @@ -92,7 +96,7 @@ impl TypedEnumDeclaration { let mut new_type_parameters = vec![]; for type_parameter in type_parameters.into_iter() { new_type_parameters.push(check!( - TypeParameter::type_check(ctx.by_ref(), type_parameter), + TypeParameter::type_check(ctx.by_ref(), type_engine, type_parameter), return err(warnings, errors), warnings, errors @@ -103,7 +107,7 @@ impl TypedEnumDeclaration { let mut variants_buf = vec![]; for variant in variants { variants_buf.push(check!( - TypedEnumVariant::type_check(ctx.by_ref(), variant.clone()), + TypedEnumVariant::type_check(ctx.by_ref(), type_engine, variant.clone()), continue, warnings, errors @@ -176,8 +180,9 @@ impl PartialEq for TypedEnumVariant { } impl CopyTypes for TypedEnumVariant { - fn copy_types(&mut self, type_mapping: &TypeMapping) { - self.type_id.update_type(type_mapping, &self.span); + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { + self.type_id + .update_type(type_engine, type_mapping, &self.span); } } @@ -206,18 +211,20 @@ impl ReplaceSelfType for TypedEnumVariant { impl TypedEnumVariant { pub(crate) fn type_check( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, variant: EnumVariant, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; let enum_variant_type = check!( ctx.resolve_type_with_self( - insert_type(variant.type_info), + type_engine, + type_engine.insert_type(variant.type_info), &variant.span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/function.rs b/sway-core/src/semantic_analysis/ast_node/declaration/function.rs index 6eb589d3856..0c85d374b57 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/function.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/function.rs @@ -51,16 +51,16 @@ impl PartialEq for TypedFunctionDeclaration { } impl CopyTypes for TypedFunctionDeclaration { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { self.type_parameters .iter_mut() - .for_each(|x| x.copy_types(type_mapping)); + .for_each(|x| x.copy_types(type_engine, type_mapping)); self.parameters .iter_mut() - .for_each(|x| x.copy_types(type_mapping)); + .for_each(|x| x.copy_types(type_engine, type_mapping)); self.return_type - .update_type(type_mapping, &self.return_type_span); - self.body.copy_types(type_mapping); + .update_type(type_engine, type_mapping, &self.return_type_span); + self.body.copy_types(type_engine, type_mapping); } } @@ -114,7 +114,11 @@ impl ToJsonAbi for TypedFunctionDeclaration { } impl TypedFunctionDeclaration { - pub fn type_check(ctx: TypeCheckContext, fn_decl: FunctionDeclaration) -> CompileResult { + pub fn type_check( + ctx: TypeCheckContext, + type_engine: &TypeEngine, + fn_decl: FunctionDeclaration, + ) -> CompileResult { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -142,7 +146,7 @@ impl TypedFunctionDeclaration { let mut new_type_parameters = vec![]; for type_parameter in type_parameters.into_iter() { new_type_parameters.push(check!( - TypeParameter::type_check(ctx.by_ref(), type_parameter), + TypeParameter::type_check(ctx.by_ref(), type_engine, type_parameter), return err(warnings, errors), warnings, errors @@ -154,7 +158,7 @@ impl TypedFunctionDeclaration { let mut new_parameters = vec![]; for parameter in parameters.into_iter() { new_parameters.push(check!( - TypedFunctionParameter::type_check(ctx.by_ref(), parameter), + TypedFunctionParameter::type_check(ctx.by_ref(), type_engine, parameter), continue, warnings, errors @@ -164,12 +168,13 @@ impl TypedFunctionDeclaration { // type check the return type let return_type = check!( ctx.resolve_type_with_self( - insert_type(return_type), + type_engine, + type_engine.insert_type(return_type), &return_type_span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); @@ -184,10 +189,10 @@ impl TypedFunctionDeclaration { .with_help_text("Function body's return type does not match up with its return type annotation.") .with_type_annotation(return_type); check!( - TypedCodeBlock::type_check(ctx, body), + TypedCodeBlock::type_check(ctx, type_engine, body), ( TypedCodeBlock { contents: vec![] }, - insert_type(TypeInfo::ErrorRecovery) + type_engine.insert_type(TypeInfo::ErrorRecovery) ), warnings, errors @@ -324,6 +329,8 @@ fn test_function_selector_behavior() { assert_eq!(selector_text, "foo()".to_string()); + let type_engine = TypeEngine::default(); + let decl = TypedFunctionDeclaration { purity: Default::default(), name: Ident::new_with_override("bar", Span::dummy()), @@ -332,13 +339,13 @@ fn test_function_selector_behavior() { TypedFunctionParameter { name: Ident::new_no_span("foo"), is_mutable: false, - type_id: crate::type_system::insert_type(TypeInfo::Str(5)), + type_id: type_engine.insert_type(TypeInfo::Str(5)), type_span: Span::dummy(), }, TypedFunctionParameter { name: Ident::new_no_span("baz"), is_mutable: false, - type_id: insert_type(TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo)), + type_id: type_engine.insert_type(TypeInfo::UnsignedInteger(IntegerBits::ThirtyTwo)), type_span: Span::dummy(), }, ], diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs b/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs index 51c11f88110..f419d6ddc15 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/function/function_parameter.rs @@ -30,8 +30,9 @@ impl PartialEq for TypedFunctionParameter { } impl CopyTypes for TypedFunctionParameter { - fn copy_types(&mut self, type_mapping: &TypeMapping) { - self.type_id.update_type(type_mapping, &self.type_span); + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { + self.type_id + .update_type(type_engine, type_mapping, &self.type_span); } } @@ -42,18 +43,20 @@ impl TypedFunctionParameter { pub(crate) fn type_check( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, parameter: FunctionParameter, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; let type_id = check!( ctx.resolve_type_with_self( + type_engine, parameter.type_id, ¶meter.type_span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); 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 74263f5da55..4b0e19fd602 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 @@ -9,8 +9,8 @@ use crate::{ TypedIntrinsicFunctionKind, TypedReturnStatement, TypedWhileLoop, }, type_system::{ - insert_type, look_up_type_id, resolve_type, set_type_as_storage_only, unify_with_self, - CopyTypes, TypeId, TypeMapping, TypeParameter, + look_up_type_id, resolve_type, set_type_as_storage_only, unify_with_self, CopyTypes, + TypeEngine, TypeId, TypeMapping, TypeParameter, }, CallPath, CompileError, CompileResult, FunctionDeclaration, ImplSelf, ImplTrait, Purity, TypeInfo, TypedDeclaration, TypedFunctionDeclaration, @@ -27,16 +27,17 @@ pub struct TypedImplTrait { } impl CopyTypes for TypedImplTrait { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { self.methods .iter_mut() - .for_each(|x| x.copy_types(type_mapping)); + .for_each(|x| x.copy_types(type_engine, type_mapping)); } } impl TypedImplTrait { pub(crate) fn type_check_impl_trait( ctx: TypeCheckContext, + type_engine: &TypeEngine, impl_trait: ImplTrait, ) -> CompileResult<(Self, TypeId)> { let mut errors = vec![]; @@ -61,7 +62,7 @@ impl TypedImplTrait { let mut new_type_parameters = vec![]; for type_parameter in type_parameters.into_iter() { new_type_parameters.push(check!( - TypeParameter::type_check(ctx.by_ref(), type_parameter), + TypeParameter::type_check(ctx.by_ref(), type_engine, type_parameter), return err(warnings, errors), warnings, errors @@ -71,7 +72,8 @@ impl TypedImplTrait { // type check the type that we are implementing for let implementing_for_type_id = check!( ctx.resolve_type_without_self( - insert_type(type_implementing_for), + type_engine, + type_engine.insert_type(type_implementing_for), &type_implementing_for_span, None ), @@ -105,6 +107,7 @@ impl TypedImplTrait { let functions_buf = check!( type_check_trait_implementation( ctx, + type_engine, &tr.interface_surface, &tr.methods, &functions, @@ -122,7 +125,7 @@ impl TypedImplTrait { methods: functions_buf, implementing_for_type_id, }; - let implementing_for_type_id = insert_type( + let implementing_for_type_id = type_engine.insert_type( match resolve_type(implementing_for_type_id, &type_implementing_for_span) { Ok(o) => o, Err(e) => { @@ -150,6 +153,7 @@ impl TypedImplTrait { let functions_buf = check!( type_check_trait_implementation( ctx, + type_engine, &abi.interface_surface, &abi.methods, &functions, @@ -302,6 +306,7 @@ impl TypedImplTrait { pub(crate) fn type_check_impl_self( ctx: TypeCheckContext, + type_engine: &TypeEngine, impl_self: ImplSelf, ) -> CompileResult { let mut warnings = vec![]; @@ -334,7 +339,7 @@ impl TypedImplTrait { let mut new_type_parameters = vec![]; for type_parameter in type_parameters.into_iter() { new_type_parameters.push(check!( - TypeParameter::type_check(ctx.by_ref(), type_parameter), + TypeParameter::type_check(ctx.by_ref(), type_engine, type_parameter), return err(warnings, errors), warnings, errors @@ -344,7 +349,8 @@ impl TypedImplTrait { // type check the type that we are implementing for let implementing_for_type_id = check!( ctx.resolve_type_without_self( - insert_type(type_implementing_for), + type_engine, + type_engine.insert_type(type_implementing_for), &type_implementing_for_span, None ), @@ -368,13 +374,13 @@ impl TypedImplTrait { let mut ctx = ctx .with_self_type(implementing_for_type_id) .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); // type check the methods inside of the impl block let mut methods = vec![]; for fn_decl in functions.into_iter() { methods.push(check!( - TypedFunctionDeclaration::type_check(ctx.by_ref(), fn_decl), + TypedFunctionDeclaration::type_check(ctx.by_ref(), type_engine, fn_decl), continue, warnings, errors @@ -396,6 +402,7 @@ impl TypedImplTrait { #[allow(clippy::too_many_arguments)] fn type_check_trait_implementation( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, trait_interface_surface: &[TypedTraitFn], trait_methods: &[FunctionDeclaration], functions: &[FunctionDeclaration], @@ -420,11 +427,11 @@ fn type_check_trait_implementation( let mut ctx = ctx .by_ref() .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); // type check the function declaration let fn_decl = check!( - TypedFunctionDeclaration::type_check(ctx.by_ref(), fn_decl.clone()), + TypedFunctionDeclaration::type_check(ctx.by_ref(), type_engine, fn_decl.clone()), continue, warnings, errors @@ -551,13 +558,14 @@ fn type_check_trait_implementation( .concat(); ctx.namespace.star_import(&trait_path); - let self_type_id = insert_type(match resolve_type(ctx.self_type(), self_type_span) { - Ok(o) => o, - Err(e) => { - errors.push(e.into()); - return err(warnings, errors); - } - }); + let self_type_id = + type_engine.insert_type(match resolve_type(ctx.self_type(), self_type_span) { + Ok(o) => o, + Err(e) => { + errors.push(e.into()); + return err(warnings, errors); + } + }); ctx.namespace.insert_trait_implementation( CallPath { prefixes: vec![], @@ -570,7 +578,7 @@ fn type_check_trait_implementation( let mut ctx = ctx .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); // type check the methods now that the interface // they depends upon has been implemented @@ -578,7 +586,7 @@ fn type_check_trait_implementation( // into it as a trait implementation for this for method in trait_methods { let method = check!( - TypedFunctionDeclaration::type_check(ctx.by_ref(), method.clone()), + TypedFunctionDeclaration::type_check(ctx.by_ref(), type_engine, method.clone()), continue, warnings, errors diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs b/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs index c13500f6783..80eba16e8df 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/struct.rs @@ -24,19 +24,19 @@ impl PartialEq for TypedStructDeclaration { } impl CopyTypes for TypedStructDeclaration { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { self.fields .iter_mut() - .for_each(|x| x.copy_types(type_mapping)); + .for_each(|x| x.copy_types(type_engine, type_mapping)); self.type_parameters .iter_mut() - .for_each(|x| x.copy_types(type_mapping)); + .for_each(|x| x.copy_types(type_engine, type_mapping)); } } impl CreateTypeId for TypedStructDeclaration { - fn create_type_id(&self) -> TypeId { - insert_type(TypeInfo::Struct { + fn create_type_id(&self, type_engine: &TypeEngine) -> TypeId { + type_engine.insert_type(TypeInfo::Struct { name: self.name.clone(), fields: self.fields.clone(), type_parameters: self.type_parameters.clone(), @@ -63,6 +63,7 @@ impl MonomorphizeHelper for TypedStructDeclaration { impl TypedStructDeclaration { pub(crate) fn type_check( ctx: TypeCheckContext, + type_engine: &TypeEngine, decl: StructDeclaration, ) -> CompileResult { let mut warnings = vec![]; @@ -85,7 +86,7 @@ impl TypedStructDeclaration { let mut new_type_parameters = vec![]; for type_parameter in type_parameters.into_iter() { new_type_parameters.push(check!( - TypeParameter::type_check(ctx.by_ref(), type_parameter), + TypeParameter::type_check(ctx.by_ref(), type_engine, type_parameter), return err(warnings, errors), warnings, errors @@ -96,7 +97,7 @@ impl TypedStructDeclaration { let mut new_fields = vec![]; for field in fields.into_iter() { new_fields.push(check!( - TypedStructField::type_check(ctx.by_ref(), field), + TypedStructField::type_check(ctx.by_ref(), type_engine, field), return err(warnings, errors), warnings, errors @@ -169,8 +170,9 @@ impl PartialEq for TypedStructField { } impl CopyTypes for TypedStructField { - fn copy_types(&mut self, type_mapping: &TypeMapping) { - self.type_id.update_type(type_mapping, &self.span); + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { + self.type_id + .update_type(type_engine, type_mapping, &self.span); } } @@ -197,17 +199,22 @@ impl ReplaceSelfType for TypedStructField { } impl TypedStructField { - pub(crate) fn type_check(mut ctx: TypeCheckContext, field: StructField) -> CompileResult { + pub(crate) fn type_check( + mut ctx: TypeCheckContext, + type_engine: &TypeEngine, + field: StructField, + ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; let r#type = check!( ctx.resolve_type_with_self( - insert_type(field.type_info), + type_engine, + type_engine.insert_type(field.type_info), &field.type_span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); 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 df6926688fe..f33d3b6c702 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/trait.rs @@ -8,7 +8,7 @@ use crate::{ Mode, TypeCheckContext, TypedCodeBlock, }, style::is_upper_camel_case, - type_system::{insert_type, CopyTypes, TypeMapping}, + type_system::{CopyTypes, TypeEngine, TypeMapping}, CallPath, CompileError, CompileResult, FunctionDeclaration, FunctionParameter, Namespace, Supertrait, TraitDeclaration, TypeInfo, TypedDeclaration, TypedFunctionDeclaration, Visibility, }; @@ -31,10 +31,10 @@ pub struct TypedTraitDeclaration { } impl CopyTypes for TypedTraitDeclaration { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { self.interface_surface .iter_mut() - .for_each(|x| x.copy_types(type_mapping)); + .for_each(|x| x.copy_types(type_engine, type_mapping)); // we don't have to type check the methods because it hasn't been type checked yet } } @@ -42,6 +42,7 @@ impl CopyTypes for TypedTraitDeclaration { impl TypedTraitDeclaration { pub(crate) fn type_check( ctx: TypeCheckContext, + type_engine: &TypeEngine, trait_decl: TraitDeclaration, ) -> CompileResult { let mut warnings = Vec::new(); @@ -51,7 +52,11 @@ impl TypedTraitDeclaration { // type check the interface surface let interface_surface = check!( - type_check_interface_surface(trait_decl.interface_surface.to_vec(), ctx.namespace), + type_check_interface_surface( + type_engine, + trait_decl.interface_surface.to_vec(), + ctx.namespace + ), return err(warnings, errors), warnings, errors @@ -63,7 +68,7 @@ impl TypedTraitDeclaration { // Recursively handle supertraits: make their interfaces and methods available to this trait check!( - handle_supertraits(&trait_decl.supertraits, ctx.namespace), + handle_supertraits(type_engine, &trait_decl.supertraits, ctx.namespace), return err(warnings, errors), warnings, errors @@ -77,16 +82,16 @@ impl TypedTraitDeclaration { suffix: trait_decl.name.clone(), is_absolute: false, }, - insert_type(TypeInfo::SelfType), + type_engine.insert_type(TypeInfo::SelfType), interface_surface .iter() .map(|x| x.to_dummy_func(Mode::NonAbi)) .collect(), ); // check the methods for errors but throw them away and use vanilla [FunctionDeclaration]s - let ctx = ctx.with_self_type(insert_type(TypeInfo::SelfType)); + let ctx = ctx.with_self_type(type_engine.insert_type(TypeInfo::SelfType)); let _methods = check!( - type_check_trait_methods(ctx, trait_decl.methods.clone()), + type_check_trait_methods(ctx, type_engine, trait_decl.methods.clone()), vec![], warnings, errors @@ -105,6 +110,7 @@ impl TypedTraitDeclaration { /// Recursively handle supertraits by adding all their interfaces and methods to some namespace /// which is meant to be the namespace of the subtrait in question fn handle_supertraits( + type_engine: &TypeEngine, supertraits: &[Supertrait], trait_namespace: &mut Namespace, ) -> CompileResult<()> { @@ -126,7 +132,7 @@ fn handle_supertraits( // insert dummy versions of the interfaces for all of the supertraits trait_namespace.insert_trait_implementation( supertrait.name.clone(), - insert_type(TypeInfo::SelfType), + type_engine.insert_type(TypeInfo::SelfType), interface_surface .iter() .map(|x| x.to_dummy_func(Mode::NonAbi)) @@ -135,21 +141,21 @@ fn handle_supertraits( // insert dummy versions of the methods of all of the supertraits let dummy_funcs = check!( - convert_trait_methods_to_dummy_funcs(methods, trait_namespace), + convert_trait_methods_to_dummy_funcs(type_engine, methods, trait_namespace), return err(warnings, errors), warnings, errors ); trait_namespace.insert_trait_implementation( supertrait.name.clone(), - insert_type(TypeInfo::SelfType), + type_engine.insert_type(TypeInfo::SelfType), dummy_funcs, ); // Recurse to insert dummy versions of interfaces and methods of the *super* // supertraits check!( - handle_supertraits(supertraits, trait_namespace), + handle_supertraits(type_engine, supertraits, trait_namespace), return err(warnings, errors), warnings, errors @@ -172,6 +178,7 @@ fn handle_supertraits( /// Convert a vector of FunctionDeclarations into a vector of TypedFunctionDeclarations where only /// the parameters and the return types are type checked. fn convert_trait_methods_to_dummy_funcs( + type_engine: &TypeEngine, methods: &[FunctionDeclaration], trait_namespace: &mut Namespace, ) -> CompileResult> { @@ -203,13 +210,14 @@ fn convert_trait_methods_to_dummy_funcs( is_mutable: *is_mutable, type_id: check!( trait_namespace.resolve_type_with_self( + type_engine, *type_id, - insert_type(TypeInfo::SelfType), + type_engine.insert_type(TypeInfo::SelfType), type_span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ), @@ -220,13 +228,14 @@ fn convert_trait_methods_to_dummy_funcs( span: name.span(), return_type: check!( trait_namespace.resolve_type_with_self( - insert_type(return_type.clone()), - insert_type(TypeInfo::SelfType), + type_engine, + type_engine.insert_type(return_type.clone()), + type_engine.insert_type(TypeInfo::SelfType), return_type_span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ), diff --git a/sway-core/src/semantic_analysis/ast_node/declaration/variable.rs b/sway-core/src/semantic_analysis/ast_node/declaration/variable.rs index 1169adae26e..6f734ca61be 100644 --- a/sway-core/src/semantic_analysis/ast_node/declaration/variable.rs +++ b/sway-core/src/semantic_analysis/ast_node/declaration/variable.rs @@ -67,9 +67,9 @@ impl PartialEq for TypedVariableDeclaration { } impl CopyTypes for TypedVariableDeclaration { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { self.type_ascription - .update_type(type_mapping, &self.body.span); - self.body.copy_types(type_mapping) + .update_type(type_engine, type_mapping, &self.body.span); + self.body.copy_types(type_engine, type_mapping) } } diff --git a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs index 7bb0c7b4326..c1348f51039 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/intrinsic_function.rs @@ -23,12 +23,13 @@ pub struct TypedIntrinsicFunctionKind { } impl CopyTypes for TypedIntrinsicFunctionKind { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { for arg in &mut self.arguments { - arg.copy_types(type_mapping); + arg.copy_types(type_engine, type_mapping); } for targ in &mut self.type_arguments { - targ.type_id.update_type(type_mapping, &targ.span); + targ.type_id + .update_type(type_engine, type_mapping, &targ.span); } } } @@ -69,6 +70,7 @@ impl UnresolvedTypeCheck for TypedIntrinsicFunctionKind { impl TypedIntrinsicFunctionKind { pub(crate) fn type_check( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, kind_binding: TypeBinding, arguments: Vec, span: Span, @@ -92,9 +94,9 @@ impl TypedIntrinsicFunctionKind { } let ctx = ctx .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); let exp = check!( - TypedExpression::type_check(ctx, arguments[0].clone()), + TypedExpression::type_check(ctx, type_engine, arguments[0].clone()), return err(warnings, errors), warnings, errors @@ -105,7 +107,8 @@ impl TypedIntrinsicFunctionKind { type_arguments: vec![], span, }; - let return_type = insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)); + let return_type = + type_engine.insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)); (intrinsic_function, return_type) } Intrinsic::SizeOfType => { @@ -128,12 +131,13 @@ impl TypedIntrinsicFunctionKind { let targ = type_arguments[0].clone(); let type_id = check!( ctx.resolve_type_with_self( - insert_type(resolve_type(targ.type_id, &targ.span).unwrap()), + type_engine, + type_engine.insert_type(resolve_type(targ.type_id, &targ.span).unwrap()), &targ.span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); @@ -146,7 +150,8 @@ impl TypedIntrinsicFunctionKind { }], span, }; - let return_type = insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)); + let return_type = + type_engine.insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)); (intrinsic_function, return_type) } Intrinsic::IsReferenceType => { @@ -161,12 +166,13 @@ impl TypedIntrinsicFunctionKind { let targ = type_arguments[0].clone(); let type_id = check!( ctx.resolve_type_with_self( - insert_type(resolve_type(targ.type_id, &targ.span).unwrap()), + type_engine, + type_engine.insert_type(resolve_type(targ.type_id, &targ.span).unwrap()), &targ.span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); @@ -179,7 +185,10 @@ impl TypedIntrinsicFunctionKind { }], span, }; - (intrinsic_function, insert_type(TypeInfo::Boolean)) + ( + intrinsic_function, + type_engine.insert_type(TypeInfo::Boolean), + ) } Intrinsic::GetStorageKey => ( TypedIntrinsicFunctionKind { @@ -188,7 +197,7 @@ impl TypedIntrinsicFunctionKind { type_arguments: vec![], span, }, - insert_type(TypeInfo::B256), + type_engine.insert_type(TypeInfo::B256), ), Intrinsic::Eq => { if arguments.len() != 2 { @@ -201,11 +210,11 @@ impl TypedIntrinsicFunctionKind { } let mut ctx = ctx .by_ref() - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); let lhs = arguments[0].clone(); let lhs = check!( - TypedExpression::type_check(ctx.by_ref(), lhs), + TypedExpression::type_check(ctx.by_ref(), type_engine, lhs), return err(warnings, errors), warnings, errors @@ -230,7 +239,7 @@ impl TypedIntrinsicFunctionKind { .with_help_text("Incorrect argument type") .with_type_annotation(lhs.return_type); let rhs = check!( - TypedExpression::type_check(ctx, rhs), + TypedExpression::type_check(ctx, type_engine, rhs), return err(warnings, errors), warnings, errors @@ -242,7 +251,7 @@ impl TypedIntrinsicFunctionKind { type_arguments: vec![], span, }, - insert_type(TypeInfo::Boolean), + type_engine.insert_type(TypeInfo::Boolean), ) } Intrinsic::Gtf => { @@ -267,9 +276,9 @@ impl TypedIntrinsicFunctionKind { // Type check the first argument which is the index let mut ctx = ctx .by_ref() - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); let index = check!( - TypedExpression::type_check(ctx.by_ref(), arguments[0].clone()), + TypedExpression::type_check(ctx.by_ref(), type_engine, arguments[0].clone()), return err(warnings, errors), warnings, errors @@ -278,9 +287,9 @@ impl TypedIntrinsicFunctionKind { // Type check the second argument which is the tx field ID let mut ctx = ctx .by_ref() - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); let tx_field_id = check!( - TypedExpression::type_check(ctx.by_ref(), arguments[1].clone()), + TypedExpression::type_check(ctx.by_ref(), type_engine, arguments[1].clone()), return err(warnings, errors), warnings, errors @@ -313,12 +322,13 @@ impl TypedIntrinsicFunctionKind { let targ = type_arguments[0].clone(); let type_id = check!( ctx.resolve_type_with_self( - insert_type(resolve_type(targ.type_id, &targ.span).unwrap()), + type_engine, + type_engine.insert_type(resolve_type(targ.type_id, &targ.span).unwrap()), &targ.span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); @@ -347,9 +357,9 @@ impl TypedIntrinsicFunctionKind { } let ctx = ctx .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); let exp = check!( - TypedExpression::type_check(ctx, arguments[0].clone()), + TypedExpression::type_check(ctx, type_engine, arguments[0].clone()), return err(warnings, errors), warnings, errors @@ -372,7 +382,8 @@ impl TypedIntrinsicFunctionKind { type_arguments: vec![], span, }; - let return_type = insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)); + let return_type = + type_engine.insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)); (intrinsic_function, return_type) } }; diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/matcher.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/matcher.rs index 985876cbe6e..2c343441bb8 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/matcher.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/matcher.rs @@ -8,7 +8,7 @@ use crate::{ namespace::Namespace, IsConstant, TypedEnumVariant, TypedExpression, TypedExpressionVariant, }, - type_system::unify, + type_system::{unify, TypeEngine}, CompileResult, Ident, Literal, }; @@ -64,6 +64,7 @@ pub(crate) type MatcherResult = (MatchReqMap, MatchDeclMap); /// ] /// ``` pub(crate) fn matcher( + type_engine: &TypeEngine, exp: &TypedExpression, scrutinee: TypedScrutinee, namespace: &mut Namespace, @@ -85,11 +86,15 @@ pub(crate) fn matcher( TypedScrutineeVariant::CatchAll => ok((vec![], vec![]), warnings, errors), TypedScrutineeVariant::Literal(value) => match_literal(exp, value, span), TypedScrutineeVariant::Variable(name) => match_variable(exp, name, span), - TypedScrutineeVariant::StructScrutinee(fields) => match_struct(exp, fields, namespace), + TypedScrutineeVariant::StructScrutinee(fields) => { + match_struct(type_engine, exp, fields, namespace) + } TypedScrutineeVariant::EnumScrutinee { value, variant } => { - match_enum(exp, variant, *value, span, namespace) + match_enum(type_engine, exp, variant, *value, span, namespace) + } + TypedScrutineeVariant::Tuple(elems) => { + match_tuple(type_engine, exp, elems, span, namespace) } - TypedScrutineeVariant::Tuple(elems) => match_tuple(exp, elems, span, namespace), } } @@ -122,6 +127,7 @@ fn match_variable( } fn match_struct( + type_engine: &TypeEngine, exp: &TypedExpression, fields: Vec, namespace: &mut Namespace, @@ -150,7 +156,7 @@ fn match_struct( // or if the scrutinee has a more complex agenda Some(scrutinee) => { let (mut new_match_req_map, mut new_match_decl_map) = check!( - matcher(&subfield, scrutinee, namespace), + matcher(type_engine, &subfield, scrutinee, namespace), return err(warnings, errors), warnings, errors @@ -165,6 +171,7 @@ fn match_struct( } fn match_enum( + type_engine: &TypeEngine, exp: &TypedExpression, variant: TypedEnumVariant, scrutinee: TypedScrutinee, @@ -173,9 +180,10 @@ fn match_enum( ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; - let (mut match_req_map, unsafe_downcast) = instantiate_unsafe_downcast(exp, variant, span); + let (mut match_req_map, unsafe_downcast) = + instantiate_unsafe_downcast(type_engine, exp, variant, span); let (mut new_match_req_map, match_decl_map) = check!( - matcher(&unsafe_downcast, scrutinee, namespace), + matcher(type_engine, &unsafe_downcast, scrutinee, namespace), return err(warnings, errors), warnings, errors @@ -185,6 +193,7 @@ fn match_enum( } fn match_tuple( + type_engine: &TypeEngine, exp: &TypedExpression, elems: Vec, span: Span, @@ -202,7 +211,7 @@ fn match_tuple( errors ); let (mut new_match_req_map, mut new_match_decl_map) = check!( - matcher(&tuple_index_access, elem, namespace), + matcher(type_engine, &tuple_index_access, elem, namespace), return err(warnings, errors), warnings, errors diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs index 1a35ee5dd25..91cbb2ba87a 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_branch.rs @@ -7,7 +7,7 @@ use crate::{ TypeCheckContext, TypedAstNode, TypedAstNodeContent, TypedCodeBlock, TypedExpression, TypedExpressionVariant, TypedVariableDeclaration, VariableMutability, }, - type_system::insert_type, + type_system::TypeEngine, types::DeterministicallyAborts, CompileResult, MatchBranch, TypeInfo, TypedDeclaration, }; @@ -25,6 +25,7 @@ pub(crate) struct TypedMatchBranch { impl TypedMatchBranch { pub(crate) fn type_check( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, typed_value: &TypedExpression, branch: MatchBranch, ) -> CompileResult { @@ -39,7 +40,7 @@ impl TypedMatchBranch { // type check the scrutinee let typed_scrutinee = check!( - TypedScrutinee::type_check(ctx.by_ref(), scrutinee), + TypedScrutinee::type_check(ctx.by_ref(), type_engine, scrutinee), return err(warnings, errors), warnings, errors @@ -47,7 +48,7 @@ impl TypedMatchBranch { // calculate the requirements map and the declarations map let (match_req_map, match_decl_map) = check!( - matcher(typed_value, typed_scrutinee, ctx.namespace), + matcher(type_engine, typed_value, typed_scrutinee, ctx.namespace), return err(warnings, errors), warnings, errors @@ -80,9 +81,9 @@ impl TypedMatchBranch { let typed_result = { let ctx = ctx .by_ref() - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); check!( - TypedExpression::type_check(ctx, result), + TypedExpression::type_check(ctx, type_engine, result), return err(warnings, errors), warnings, errors diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs index 076a313851b..571ecee6faf 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_match_expression.rs @@ -8,7 +8,7 @@ use crate::{ }, IsConstant, TypeCheckContext, TypedExpression, TypedExpressionVariant, }, - type_system::{insert_type, TypeId}, + type_system::{TypeEngine, TypeId}, CompileError, CompileResult, LazyOp, Literal, MatchBranch, TypeInfo, }; @@ -25,6 +25,7 @@ pub(crate) struct TypedMatchExpression { impl TypedMatchExpression { pub(crate) fn type_check( ctx: TypeCheckContext, + type_engine: &TypeEngine, typed_value: TypedExpression, branches: Vec, span: Span, @@ -38,7 +39,7 @@ impl TypedMatchExpression { ctx.with_help_text("all branches of a match statement must return the same type"); for branch in branches.into_iter() { let typed_branch = check!( - TypedMatchBranch::type_check(ctx.by_ref(), &typed_value, branch), + TypedMatchBranch::type_check(ctx.by_ref(), type_engine, &typed_value, branch), continue, warnings, errors @@ -61,6 +62,7 @@ impl TypedMatchExpression { pub(crate) fn convert_to_typed_if_expression( self, mut ctx: TypeCheckContext, + type_engine: &TypeEngine, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -81,7 +83,7 @@ impl TypedMatchExpression { let joined_span = Span::join(left_req.span.clone(), right_req.span.clone()); let args = vec![left_req, right_req]; let new_condition = check!( - TypedExpression::core_ops_eq(ctx.by_ref(), args, joined_span), + TypedExpression::core_ops_eq(ctx.by_ref(), type_engine, args, joined_span), continue, warnings, errors @@ -94,7 +96,7 @@ impl TypedMatchExpression { LazyOp::And, new_condition, inner_condition, - insert_type(TypeInfo::Boolean), + type_engine.insert_type(TypeInfo::Boolean), joined_span, ) } @@ -110,6 +112,7 @@ impl TypedMatchExpression { (None, Some(conditional)) => { check!( instantiate_if_expression( + type_engine, conditional, result.clone(), Some(result), // TODO: this is a really bad hack and we should not do this @@ -125,12 +128,13 @@ impl TypedMatchExpression { (Some(prev_if_exp), None) => { let conditional = TypedExpression { expression: TypedExpressionVariant::Literal(Literal::Boolean(true)), - return_type: insert_type(TypeInfo::Boolean), + return_type: type_engine.insert_type(TypeInfo::Boolean), is_constant: IsConstant::No, span: result_span.clone(), }; check!( instantiate_if_expression( + type_engine, conditional, result, Some(prev_if_exp), @@ -146,6 +150,7 @@ impl TypedMatchExpression { (Some(prev_if_exp), Some(conditional)) => { check!( instantiate_if_expression( + type_engine, conditional, result, Some(prev_if_exp), diff --git a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs index a8ac98ed949..c54a001c96f 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/match_expression/typed/typed_scrutinee.rs @@ -3,7 +3,7 @@ use sway_types::{Ident, Span, Spanned}; use crate::{ error::{err, ok}, semantic_analysis::{TypeCheckContext, TypedEnumVariant}, - type_system::{insert_type, CreateTypeId, EnforceTypeArguments, TypeArgument, TypeId}, + type_system::{CreateTypeId, EnforceTypeArguments, TypeArgument, TypeEngine, TypeId}, CompileError, CompileResult, Literal, Scrutinee, StructScrutineeField, TypeInfo, }; @@ -38,6 +38,7 @@ pub(crate) struct TypedStructScrutineeField { impl TypedScrutinee { pub(crate) fn type_check( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, scrutinee: Scrutinee, ) -> CompileResult { let mut warnings = vec![]; @@ -45,17 +46,17 @@ impl TypedScrutinee { let typed_scrutinee = match scrutinee { Scrutinee::CatchAll { span } => TypedScrutinee { variant: TypedScrutineeVariant::CatchAll, - type_id: insert_type(TypeInfo::Unknown), + type_id: type_engine.insert_type(TypeInfo::Unknown), span, }, Scrutinee::Literal { value, span } => TypedScrutinee { variant: TypedScrutineeVariant::Literal(value.clone()), - type_id: insert_type(value.to_typeinfo()), + type_id: type_engine.insert_type(value.to_typeinfo()), span, }, Scrutinee::Variable { name, span } => TypedScrutinee { variant: TypedScrutineeVariant::Variable(name), - type_id: insert_type(TypeInfo::Unknown), + type_id: type_engine.insert_type(TypeInfo::Unknown), span, }, Scrutinee::StructScrutinee { @@ -110,7 +111,11 @@ impl TypedScrutinee { let typed_scrutinee = match scrutinee { None => None, Some(scrutinee) => Some(check!( - TypedScrutinee::type_check(ctx.by_ref(), scrutinee), + TypedScrutinee::type_check( + ctx.by_ref(), + type_engine, + scrutinee + ), return err(warnings, errors), warnings, errors @@ -142,7 +147,7 @@ impl TypedScrutinee { } TypedScrutinee { variant: TypedScrutineeVariant::StructScrutinee(typed_fields), - type_id: struct_decl.create_type_id(), + type_id: struct_decl.create_type_id(type_engine), span, } } @@ -187,7 +192,7 @@ impl TypedScrutinee { warnings, errors ); - let enum_type_id = enum_decl.create_type_id(); + let enum_type_id = enum_decl.create_type_id(type_engine); // check to see if the variant exists and grab it if it does let variant = check!( enum_decl.expect_variant_from_name(&variant_name).cloned(), @@ -197,7 +202,7 @@ impl TypedScrutinee { ); // type check the nested scrutinee let typed_value = check!( - TypedScrutinee::type_check(ctx, *value), + TypedScrutinee::type_check(ctx, type_engine, *value), return err(warnings, errors), warnings, errors @@ -215,7 +220,7 @@ impl TypedScrutinee { let mut typed_elems = vec![]; for elem in elems.into_iter() { typed_elems.push(check!( - TypedScrutinee::type_check(ctx.by_ref(), elem), + TypedScrutinee::type_check(ctx.by_ref(), type_engine, elem), continue, warnings, errors @@ -223,7 +228,7 @@ impl TypedScrutinee { } TypedScrutinee { variant: TypedScrutineeVariant::Tuple(typed_elems.clone()), - type_id: insert_type(TypeInfo::Tuple( + type_id: type_engine.insert_type(TypeInfo::Tuple( typed_elems .into_iter() .map(|x| TypeArgument { diff --git a/sway-core/src/semantic_analysis/ast_node/expression/struct_expr_field.rs b/sway-core/src/semantic_analysis/ast_node/expression/struct_expr_field.rs index 244b301a39c..a82639230c2 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/struct_expr_field.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/struct_expr_field.rs @@ -8,7 +8,7 @@ pub struct TypedStructExpressionField { } impl CopyTypes for TypedStructExpressionField { - fn copy_types(&mut self, type_mapping: &TypeMapping) { - self.value.copy_types(type_mapping); + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { + self.value.copy_types(type_engine, type_mapping); } } 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 b9dbb815b82..7a0e34bbb4b 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 @@ -46,9 +46,10 @@ impl PartialEq for TypedExpression { } impl CopyTypes for TypedExpression { - fn copy_types(&mut self, type_mapping: &TypeMapping) { - self.return_type.update_type(type_mapping, &self.span); - self.expression.copy_types(type_mapping); + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { + self.return_type + .update_type(type_engine, type_mapping, &self.span); + self.expression.copy_types(type_engine, type_mapping); } } @@ -286,10 +287,10 @@ impl DeterministicallyAborts for TypedExpression { } } -pub(crate) fn error_recovery_expr(span: Span) -> TypedExpression { +pub(crate) fn error_recovery_expr(type_engine: &TypeEngine, span: Span) -> TypedExpression { TypedExpression { expression: TypedExpressionVariant::Tuple { fields: vec![] }, - return_type: crate::type_system::insert_type(TypeInfo::ErrorRecovery), + return_type: type_engine.insert_type(TypeInfo::ErrorRecovery), is_constant: IsConstant::No, span, } @@ -299,6 +300,7 @@ pub(crate) fn error_recovery_expr(span: Span) -> TypedExpression { impl TypedExpression { pub(crate) fn core_ops_eq( ctx: TypeCheckContext, + type_engine: &TypeEngine, arguments: Vec, span: Span, ) -> CompileResult { @@ -325,7 +327,7 @@ impl TypedExpression { }; let arguments = VecDeque::from(arguments); let method = check!( - resolve_method_name(ctx, &method_name_binding, arguments.clone()), + resolve_method_name(ctx, type_engine, &method_name_binding, arguments.clone()), return err(warnings, errors), warnings, errors @@ -391,13 +393,17 @@ impl TypedExpression { } } - pub(crate) fn type_check(mut ctx: TypeCheckContext, expr: Expression) -> CompileResult { + pub(crate) fn type_check( + mut ctx: TypeCheckContext, + type_engine: &TypeEngine, + expr: Expression, + ) -> CompileResult { let expr_span = expr.span(); let span = expr_span.clone(); let res = match expr.kind { - ExpressionKind::Literal(lit) => Self::type_check_literal(lit, span), + ExpressionKind::Literal(lit) => Self::type_check_literal(type_engine, lit, span), ExpressionKind::Variable(name) => { - Self::type_check_variable_expression(ctx.namespace, name, span) + Self::type_check_variable_expression(type_engine, ctx.namespace, name, span) } ExpressionKind::FunctionApplication(function_application_expression) => { let FunctionApplicationExpression { @@ -406,6 +412,7 @@ impl TypedExpression { } = *function_application_expression; Self::type_check_function_application( ctx.by_ref(), + type_engine, call_path_binding, arguments, span, @@ -414,11 +421,11 @@ impl TypedExpression { ExpressionKind::LazyOperator(LazyOperatorExpression { op, lhs, rhs }) => { let ctx = ctx .by_ref() - .with_type_annotation(insert_type(TypeInfo::Boolean)); - Self::type_check_lazy_operator(ctx, op, *lhs, *rhs, span) + .with_type_annotation(type_engine.insert_type(TypeInfo::Boolean)); + Self::type_check_lazy_operator(ctx, type_engine, op, *lhs, *rhs, span) } ExpressionKind::CodeBlock(contents) => { - Self::type_check_code_block(ctx.by_ref(), contents, span) + Self::type_check_code_block(ctx.by_ref(), type_engine, contents, span) } // TODO if _condition_ is constant, evaluate it and compile this to an // expression with only one branch @@ -428,6 +435,7 @@ impl TypedExpression { r#else, }) => Self::type_check_if_expression( ctx.by_ref().with_help_text(""), + type_engine, *condition, *then, r#else.map(|e| *e), @@ -436,25 +444,38 @@ impl TypedExpression { ExpressionKind::Match(MatchExpression { value, branches }) => { Self::type_check_match_expression( ctx.by_ref().with_help_text(""), + type_engine, *value, branches, span, ) } - ExpressionKind::Asm(asm) => Self::type_check_asm_expression(ctx.by_ref(), *asm, span), + ExpressionKind::Asm(asm) => { + Self::type_check_asm_expression(ctx.by_ref(), type_engine, *asm, span) + } ExpressionKind::Struct(struct_expression) => { let StructExpression { call_path_binding, fields, } = *struct_expression; - Self::type_check_struct_expression(ctx.by_ref(), call_path_binding, fields, span) + Self::type_check_struct_expression( + ctx.by_ref(), + type_engine, + call_path_binding, + fields, + span, + ) } ExpressionKind::Subfield(SubfieldExpression { prefix, field_to_access, - }) => { - Self::type_check_subfield_expression(ctx.by_ref(), *prefix, span, field_to_access) - } + }) => Self::type_check_subfield_expression( + ctx.by_ref(), + type_engine, + *prefix, + span, + field_to_access, + ), ExpressionKind::MethodApplication(method_application_expression) => { let MethodApplicationExpression { method_name_binding, @@ -463,48 +484,72 @@ impl TypedExpression { } = *method_application_expression; type_check_method_application( ctx.by_ref(), + type_engine, method_name_binding, contract_call_params, arguments, span, ) } - ExpressionKind::Tuple(fields) => Self::type_check_tuple(ctx.by_ref(), fields, span), + ExpressionKind::Tuple(fields) => { + Self::type_check_tuple(ctx.by_ref(), type_engine, fields, span) + } ExpressionKind::TupleIndex(TupleIndexExpression { prefix, index, index_span, - }) => Self::type_check_tuple_index(ctx.by_ref(), *prefix, index, index_span, span), + }) => Self::type_check_tuple_index( + ctx.by_ref(), + type_engine, + *prefix, + index, + index_span, + span, + ), ExpressionKind::DelineatedPath(delineated_path_expression) => { let DelineatedPathExpression { call_path_binding, args, } = *delineated_path_expression; - Self::type_check_delineated_path(ctx.by_ref(), call_path_binding, span, args) + Self::type_check_delineated_path( + ctx.by_ref(), + type_engine, + call_path_binding, + span, + args, + ) } ExpressionKind::AbiCast(abi_cast_expression) => { let AbiCastExpression { abi_name, address } = *abi_cast_expression; - Self::type_check_abi_cast(ctx.by_ref(), abi_name, *address, span) + Self::type_check_abi_cast(ctx.by_ref(), type_engine, abi_name, *address, span) + } + ExpressionKind::Array(contents) => { + Self::type_check_array(ctx.by_ref(), type_engine, contents, span) } - ExpressionKind::Array(contents) => Self::type_check_array(ctx.by_ref(), contents, span), ExpressionKind::ArrayIndex(ArrayIndexExpression { prefix, index }) => { let ctx = ctx .by_ref() - .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)) .with_help_text(""); - Self::type_check_array_index(ctx, *prefix, *index, span) + Self::type_check_array_index(ctx, type_engine, *prefix, *index, span) } ExpressionKind::StorageAccess(StorageAccessExpression { field_names }) => { let ctx = ctx .by_ref() - .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)) .with_help_text(""); Self::type_check_storage_load(ctx, field_names, &span) } ExpressionKind::IntrinsicFunction(IntrinsicFunctionExpression { kind_binding, arguments, - }) => Self::type_check_intrinsic_function(ctx.by_ref(), kind_binding, arguments, span), + }) => Self::type_check_intrinsic_function( + ctx.by_ref(), + type_engine, + kind_binding, + arguments, + span, + ), }; let mut typed_expression = match res.value { Some(r) => r, @@ -525,12 +570,13 @@ impl TypedExpression { // The annotation may result in a cast, which is handled in the type engine. typed_expression.return_type = check!( ctx.resolve_type_with_self( + type_engine, typed_expression.return_type, &expr_span, EnforceTypeArguments::No, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); @@ -543,6 +589,7 @@ impl TypedExpression { TypeInfo::UnsignedInteger(_) | TypeInfo::Numeric => { typed_expression = check!( Self::resolve_numeric_literal( + type_engine, lit, expr_span, typed_expression.return_type @@ -560,7 +607,11 @@ impl TypedExpression { ok(typed_expression, warnings, errors) } - fn type_check_literal(lit: Literal, span: Span) -> CompileResult { + fn type_check_literal( + type_engine: &TypeEngine, + lit: Literal, + span: Span, + ) -> CompileResult { let return_type = match &lit { Literal::String(s) => TypeInfo::Str(s.as_str().len() as u64), Literal::Numeric(_) => TypeInfo::Numeric, @@ -572,7 +623,7 @@ impl TypedExpression { Literal::Byte(_) => TypeInfo::Byte, Literal::B256(_) => TypeInfo::B256, }; - let id = crate::type_system::insert_type(return_type); + let id = type_engine.insert_type(return_type); let exp = TypedExpression { expression: TypedExpressionVariant::Literal(lit), return_type: id, @@ -583,6 +634,7 @@ impl TypedExpression { } pub(crate) fn type_check_variable_expression( + type_engine: &TypeEngine, namespace: &Namespace, name: Ident, span: Span, @@ -608,7 +660,7 @@ impl TypedExpression { span, }, Some(TypedDeclaration::AbiDeclaration(decl)) => TypedExpression { - return_type: decl.create_type_id(), + return_type: decl.create_type_id(type_engine), is_constant: IsConstant::Yes, expression: TypedExpressionVariant::AbiName(AbiName::Known( decl.name.clone().into(), @@ -620,13 +672,13 @@ impl TypedExpression { name: name.clone(), what_it_is: a.friendly_name(), }); - error_recovery_expr(name.span()) + error_recovery_expr(type_engine, name.span()) } None => { errors.push(CompileError::UnknownVariable { var_name: name.clone(), }); - error_recovery_expr(name.span()) + error_recovery_expr(type_engine, name.span()) } }; ok(exp, vec![], errors) @@ -634,6 +686,7 @@ impl TypedExpression { fn type_check_function_application( ctx: TypeCheckContext, + type_engine: &TypeEngine, mut call_path_binding: TypeBinding, arguments: Vec, _span: Span, @@ -657,11 +710,18 @@ impl TypedExpression { errors ); - instantiate_function_application(ctx, function_decl, call_path_binding.inner, arguments) + instantiate_function_application( + ctx, + type_engine, + function_decl, + call_path_binding.inner, + arguments, + ) } fn type_check_lazy_operator( ctx: TypeCheckContext, + type_engine: &TypeEngine, op: LazyOp, lhs: Expression, rhs: Expression, @@ -671,15 +731,15 @@ impl TypedExpression { let mut errors = vec![]; let mut ctx = ctx.with_help_text(""); let typed_lhs = check!( - TypedExpression::type_check(ctx.by_ref(), lhs.clone()), - error_recovery_expr(lhs.span()), + TypedExpression::type_check(ctx.by_ref(), type_engine, lhs.clone()), + error_recovery_expr(type_engine, lhs.span()), warnings, errors ); let typed_rhs = check!( - TypedExpression::type_check(ctx.by_ref(), rhs.clone()), - error_recovery_expr(rhs.span()), + TypedExpression::type_check(ctx.by_ref(), type_engine, rhs.clone()), + error_recovery_expr(type_engine, rhs.span()), warnings, errors ); @@ -691,16 +751,17 @@ impl TypedExpression { fn type_check_code_block( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, contents: CodeBlock, span: Span, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; let (typed_block, block_return_type) = check!( - TypedCodeBlock::type_check(ctx.by_ref(), contents), + TypedCodeBlock::type_check(ctx.by_ref(), type_engine, contents), ( TypedCodeBlock { contents: vec![] }, - crate::type_system::insert_type(TypeInfo::Tuple(Vec::new())) + type_engine.insert_type(TypeInfo::Tuple(Vec::new())) ), warnings, errors @@ -724,6 +785,7 @@ impl TypedExpression { #[allow(clippy::type_complexity)] fn type_check_if_expression( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, condition: Expression, then: Expression, r#else: Option, @@ -735,10 +797,10 @@ impl TypedExpression { let ctx = ctx .by_ref() .with_help_text("The condition of an if expression must be a boolean expression.") - .with_type_annotation(insert_type(TypeInfo::Boolean)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Boolean)); check!( - TypedExpression::type_check(ctx, condition.clone()), - error_recovery_expr(condition.span()), + TypedExpression::type_check(ctx, type_engine, condition.clone()), + error_recovery_expr(type_engine, condition.span()), warnings, errors ) @@ -747,10 +809,10 @@ impl TypedExpression { let ctx = ctx .by_ref() .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); check!( - TypedExpression::type_check(ctx, then.clone()), - error_recovery_expr(then.span()), + TypedExpression::type_check(ctx, type_engine, then.clone()), + error_recovery_expr(type_engine, then.span()), warnings, errors ) @@ -759,16 +821,17 @@ impl TypedExpression { let ctx = ctx .by_ref() .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); check!( - TypedExpression::type_check(ctx, expr.clone()), - error_recovery_expr(expr.span()), + TypedExpression::type_check(ctx, type_engine, expr.clone()), + error_recovery_expr(type_engine, expr.span()), warnings, errors ) }); let exp = check!( instantiate_if_expression( + type_engine, condition, then, r#else, @@ -785,6 +848,7 @@ impl TypedExpression { fn type_check_match_expression( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, value: Expression, branches: Vec, span: Span, @@ -797,10 +861,10 @@ impl TypedExpression { let ctx = ctx .by_ref() .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); check!( - TypedExpression::type_check(ctx, value.clone()), - error_recovery_expr(value.span()), + TypedExpression::type_check(ctx, type_engine, value.clone()), + error_recovery_expr(type_engine, value.span()), warnings, errors ) @@ -823,7 +887,13 @@ impl TypedExpression { let typed_match_expression = { let ctx = ctx.by_ref().with_help_text(""); check!( - TypedMatchExpression::type_check(ctx, typed_value, branches, span.clone()), + TypedMatchExpression::type_check( + ctx, + type_engine, + typed_value, + branches, + span.clone() + ), return err(warnings, errors), warnings, errors @@ -855,7 +925,7 @@ impl TypedExpression { // desugar the typed match expression to a typed if expression let typed_if_exp = check!( - typed_match_expression.convert_to_typed_if_expression(ctx), + typed_match_expression.convert_to_typed_if_expression(ctx, type_engine), return err(warnings, errors), warnings, errors @@ -867,6 +937,7 @@ impl TypedExpression { #[allow(clippy::too_many_arguments)] fn type_check_asm_expression( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, asm: AsmExpression, span: Span, ) -> CompileResult { @@ -879,12 +950,13 @@ impl TypedExpression { .unwrap_or_else(|| asm.whole_block_span.clone()); let return_type = check!( ctx.resolve_type_with_self( - insert_type(asm.return_type.clone()), + type_engine, + type_engine.insert_type(asm.return_type.clone()), &asm_span, EnforceTypeArguments::No, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); @@ -899,10 +971,10 @@ impl TypedExpression { let ctx = ctx .by_ref() .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); check!( - TypedExpression::type_check(ctx, initializer.clone()), - error_recovery_expr(initializer.span()), + TypedExpression::type_check(ctx, type_engine, initializer.clone()), + error_recovery_expr(type_engine, initializer.span()), warnings, errors ) @@ -928,9 +1000,9 @@ impl TypedExpression { ok(exp, warnings, errors) } - #[allow(clippy::too_many_arguments)] fn type_check_struct_expression( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, call_path_binding: TypeBinding>, fields: Vec, span: Span, @@ -940,8 +1012,8 @@ impl TypedExpression { // type check the call path let type_id = check!( - call_path_binding.type_check_with_type_info(&mut ctx), - insert_type(TypeInfo::ErrorRecovery), + call_path_binding.type_check_with_type_info(&mut ctx, type_engine), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors ); @@ -972,7 +1044,7 @@ impl TypedExpression { name: def_field.name.clone(), value: TypedExpression { expression: TypedExpressionVariant::Tuple { fields: vec![] }, - return_type: insert_type(TypeInfo::ErrorRecovery), + return_type: type_engine.insert_type(TypeInfo::ErrorRecovery), is_constant: IsConstant::No, span: span.clone(), }, @@ -988,7 +1060,7 @@ impl TypedExpression { ) .with_type_annotation(def_field.type_id); let typed_field = check!( - TypedExpression::type_check(ctx, expr_field.value), + TypedExpression::type_check(ctx, type_engine, expr_field.value), continue, warnings, errors @@ -1027,6 +1099,7 @@ impl TypedExpression { #[allow(clippy::too_many_arguments)] fn type_check_subfield_expression( ctx: TypeCheckContext, + type_engine: &TypeEngine, prefix: Expression, span: Span, field_to_access: Ident, @@ -1035,9 +1108,9 @@ impl TypedExpression { let mut errors = vec![]; let ctx = ctx .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); let parent = check!( - TypedExpression::type_check(ctx, prefix), + TypedExpression::type_check(ctx, type_engine, prefix), return err(warnings, errors), warnings, errors @@ -1053,6 +1126,7 @@ impl TypedExpression { fn type_check_tuple( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, fields: Vec, span: Span, ) -> CompileResult { @@ -1071,15 +1145,18 @@ impl TypedExpression { let field_type = field_type_opt .as_ref() .map(|field_type_ids| field_type_ids[i].clone()) - .unwrap_or_default(); + .unwrap_or(TypeArgument { + span: Span::dummy(), + type_id: type_engine.insert_type(TypeInfo::Unknown), + }); let field_span = field.span(); let ctx = ctx .by_ref() .with_help_text("tuple field type does not match the expected type") .with_type_annotation(field_type.type_id); let typed_field = check!( - TypedExpression::type_check(ctx, field), - error_recovery_expr(field_span), + TypedExpression::type_check(ctx, type_engine, field), + error_recovery_expr(type_engine, field_span), warnings, errors ); @@ -1096,7 +1173,7 @@ impl TypedExpression { expression: TypedExpressionVariant::Tuple { fields: typed_fields, }, - return_type: crate::type_system::insert_type(TypeInfo::Tuple(typed_field_types)), + return_type: type_engine.insert_type(TypeInfo::Tuple(typed_field_types)), is_constant, span, }; @@ -1146,6 +1223,7 @@ impl TypedExpression { fn type_check_tuple_index( ctx: TypeCheckContext, + type_engine: &TypeEngine, prefix: Expression, index: usize, index_span: Span, @@ -1155,9 +1233,9 @@ impl TypedExpression { let mut errors = vec![]; let ctx = ctx .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); let parent = check!( - TypedExpression::type_check(ctx, prefix), + TypedExpression::type_check(ctx, type_engine, prefix), return err(warnings, errors), warnings, errors @@ -1173,6 +1251,7 @@ impl TypedExpression { fn type_check_delineated_path( ctx: TypeCheckContext, + type_engine: &TypeEngine, call_path_binding: TypeBinding, span: Span, args: Vec, @@ -1236,7 +1315,7 @@ impl TypedExpression { warnings.append(&mut enum_probe_warnings); errors.append(&mut enum_probe_errors); check!( - instantiate_enum(ctx, enum_decl, enum_name, variant_name, args), + instantiate_enum(ctx, type_engine, enum_decl, enum_name, variant_name, args), return err(warnings, errors), warnings, errors @@ -1246,7 +1325,13 @@ impl TypedExpression { warnings.append(&mut function_probe_warnings); errors.append(&mut function_probe_errors); check!( - instantiate_function_application(ctx, func_decl, call_path_binding.inner, args,), + instantiate_function_application( + ctx, + type_engine, + func_decl, + call_path_binding.inner, + args, + ), return err(warnings, errors), warnings, errors @@ -1286,9 +1371,9 @@ impl TypedExpression { ok(exp, warnings, errors) } - #[allow(clippy::too_many_arguments)] fn type_check_abi_cast( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, abi_name: CallPath, address: Expression, span: Span, @@ -1302,10 +1387,10 @@ impl TypedExpression { let ctx = ctx .by_ref() .with_help_text("An address that is being ABI cast must be of type b256") - .with_type_annotation(insert_type(TypeInfo::B256)); + .with_type_annotation(type_engine.insert_type(TypeInfo::B256)); check!( - TypedExpression::type_check(ctx, address), - error_recovery_expr(err_span), + TypedExpression::type_check(ctx, type_engine, address), + error_recovery_expr(type_engine, err_span), warnings, errors ) @@ -1354,7 +1439,7 @@ impl TypedExpression { AbiName::Deferred => { return ok( TypedExpression { - return_type: insert_type(TypeInfo::ContractCaller { + return_type: type_engine.insert_type(TypeInfo::ContractCaller { abi_name: AbiName::Deferred, address: None, }), @@ -1377,7 +1462,7 @@ impl TypedExpression { } }; - let return_type = insert_type(TypeInfo::ContractCaller { + let return_type = type_engine.insert_type(TypeInfo::ContractCaller { abi_name: AbiName::Known(abi_name.clone()), address: Some(Box::new(address_expr.clone())), }); @@ -1394,10 +1479,10 @@ impl TypedExpression { let ctx = ctx .by_ref() .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)) .with_mode(Mode::ImplAbiFn); type_checked_fn_buf.push(check!( - TypedFunctionDeclaration::type_check(ctx, method.clone()), + TypedFunctionDeclaration::type_check(ctx, type_engine, method.clone()), return err(warnings, errors), warnings, errors @@ -1422,6 +1507,7 @@ impl TypedExpression { fn type_check_array( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, contents: Vec, span: Span, ) -> CompileResult { @@ -1431,7 +1517,10 @@ impl TypedExpression { expression: TypedExpressionVariant::Array { contents: Vec::new(), }, - return_type: insert_type(TypeInfo::Array(insert_type(TypeInfo::Unknown), 0)), + return_type: type_engine.insert_type(TypeInfo::Array( + type_engine.insert_type(TypeInfo::Unknown), + 0, + )), is_constant: IsConstant::Yes, span, }, @@ -1449,10 +1538,10 @@ impl TypedExpression { let ctx = ctx .by_ref() .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); check!( - Self::type_check(ctx, expr), - error_recovery_expr(span), + Self::type_check(ctx, type_engine, expr), + error_recovery_expr(type_engine, span), warnings, errors ) @@ -1482,7 +1571,7 @@ impl TypedExpression { expression: TypedExpressionVariant::Array { contents: typed_contents, }, - return_type: insert_type(TypeInfo::Array(elem_type, array_count)), + return_type: type_engine.insert_type(TypeInfo::Array(elem_type, array_count)), is_constant: IsConstant::No, // Maybe? span, }, @@ -1493,6 +1582,7 @@ impl TypedExpression { fn type_check_array_index( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, prefix: Expression, index: Expression, span: Span, @@ -1504,9 +1594,9 @@ impl TypedExpression { let ctx = ctx .by_ref() .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); check!( - TypedExpression::type_check(ctx, prefix.clone()), + TypedExpression::type_check(ctx, type_engine, prefix.clone()), return err(warnings, errors), warnings, errors @@ -1518,9 +1608,9 @@ impl TypedExpression { let type_info_u64 = TypeInfo::UnsignedInteger(IntegerBits::SixtyFour); let ctx = ctx .with_help_text("") - .with_type_annotation(insert_type(type_info_u64)); + .with_type_annotation(type_engine.insert_type(type_info_u64)); let index_te = check!( - TypedExpression::type_check(ctx, index), + TypedExpression::type_check(ctx, type_engine, index), return err(warnings, errors), warnings, errors @@ -1555,12 +1645,20 @@ impl TypedExpression { type_arguments: vec![], span: span.clone(), }; - type_check_method_application(ctx, method_name, vec![], vec![prefix, index], span) + type_check_method_application( + ctx, + type_engine, + method_name, + vec![], + vec![prefix, index], + span, + ) } } fn type_check_intrinsic_function( ctx: TypeCheckContext, + type_engine: &TypeEngine, kind_binding: TypeBinding, arguments: Vec, span: Span, @@ -1568,7 +1666,13 @@ impl TypedExpression { let mut warnings = vec![]; let mut errors = vec![]; let (intrinsic_function, return_type) = check!( - TypedIntrinsicFunctionKind::type_check(ctx, kind_binding, arguments, span.clone()), + TypedIntrinsicFunctionKind::type_check( + ctx, + type_engine, + kind_binding, + arguments, + span.clone() + ), return err(warnings, errors), warnings, errors @@ -1583,6 +1687,7 @@ impl TypedExpression { } fn resolve_numeric_literal( + type_engine: &TypeEngine, lit: Literal, span: Span, new_type: TypeId, @@ -1642,7 +1747,7 @@ impl TypedExpression { span.clone(), ) }), - insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)), + type_engine.insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)), ), _ => unreachable!("Unexpected type for integer literals"), }, @@ -1661,7 +1766,7 @@ impl TypedExpression { } Err(e) => { errors.push(e); - let exp = error_recovery_expr(span); + let exp = error_recovery_expr(type_engine, span); ok(exp, vec![], errors) } } @@ -1672,16 +1777,26 @@ impl TypedExpression { mod tests { use super::*; - fn do_type_check(expr: Expression, type_annotation: TypeId) -> CompileResult { + fn do_type_check( + type_engine: &TypeEngine, + expr: Expression, + type_annotation: TypeId, + ) -> CompileResult { let mut namespace = Namespace::init_root(namespace::Module::default()); - let ctx = TypeCheckContext::from_root(&mut namespace).with_type_annotation(type_annotation); - TypedExpression::type_check(ctx, expr) + let ctx = TypeCheckContext::from_root(&mut namespace, type_engine) + .with_type_annotation(type_annotation); + TypedExpression::type_check(ctx, type_engine, expr) } fn do_type_check_for_boolx2(expr: Expression) -> CompileResult { + let type_engine = TypeEngine::default(); do_type_check( + &type_engine, expr, - insert_type(TypeInfo::Array(insert_type(TypeInfo::Boolean), 2)), + type_engine.insert_type(TypeInfo::Array( + type_engine.insert_type(TypeInfo::Boolean), + 2, + )), ) } @@ -1786,10 +1901,15 @@ mod tests { kind: ExpressionKind::Array(Vec::new()), span: Span::dummy(), }; + let type_engine = TypeEngine::default(); let comp_res = do_type_check( + &type_engine, expr, - insert_type(TypeInfo::Array(insert_type(TypeInfo::Boolean), 0)), + type_engine.insert_type(TypeInfo::Array( + type_engine.insert_type(TypeInfo::Boolean), + 0, + )), ); assert!(comp_res.warnings.is_empty() && comp_res.errors.is_empty()); } diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/enum_instantiation.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/enum_instantiation.rs index 2a9ac78c515..50bab64d6b5 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/enum_instantiation.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/enum_instantiation.rs @@ -7,6 +7,7 @@ use sway_types::{Ident, Spanned}; #[allow(clippy::too_many_arguments)] pub(crate) fn instantiate_enum( ctx: TypeCheckContext, + type_engine: &TypeEngine, enum_decl: TypedEnumDeclaration, enum_name: Ident, enum_variant_name: Ident, @@ -30,7 +31,7 @@ pub(crate) fn instantiate_enum( match (&args[..], look_up_type_id(enum_variant.type_id)) { ([], ty) if ty.is_unit() => ok( TypedExpression { - return_type: enum_decl.create_type_id(), + return_type: enum_decl.create_type_id(type_engine), expression: TypedExpressionVariant::EnumInstantiation { tag: enum_variant.tag, contents: None, @@ -50,7 +51,7 @@ pub(crate) fn instantiate_enum( .with_help_text("Enum instantiator must match its declared variant type.") .with_type_annotation(enum_variant.type_id); let typed_expr = check!( - TypedExpression::type_check(ctx, single_expr.clone()), + TypedExpression::type_check(ctx, type_engine, single_expr.clone()), return err(warnings, errors), warnings, errors @@ -61,7 +62,7 @@ pub(crate) fn instantiate_enum( ok( TypedExpression { - return_type: enum_decl.create_type_id(), + return_type: enum_decl.create_type_id(type_engine), expression: TypedExpressionVariant::EnumInstantiation { tag: enum_variant.tag, contents: Some(Box::new(typed_expr)), 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 24813294869..61d0945b07e 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 @@ -8,6 +8,7 @@ use sway_types::{state::StateIndex, Spanned}; #[allow(clippy::too_many_arguments)] pub(crate) fn instantiate_function_application( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, function_decl: TypedFunctionDeclaration, call_path: CallPath, arguments: Vec, @@ -47,8 +48,8 @@ pub(crate) fn instantiate_function_application( ) .with_type_annotation(param.type_id); let exp = check!( - TypedExpression::type_check(ctx, arg.clone()), - error_recovery_expr(arg.span()), + TypedExpression::type_check(ctx, type_engine, arg.clone()), + error_recovery_expr(type_engine, arg.span()), warnings, errors ); diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs index 05e498fd6e0..5cfc0266367 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/if_expression.rs @@ -5,6 +5,7 @@ use crate::{error::*, semantic_analysis::*, type_system::*, types::Deterministic use super::TypedExpression; pub(crate) fn instantiate_if_expression( + type_engine: &TypeEngine, condition: TypedExpression, then: TypedExpression, r#else: Option, @@ -22,7 +23,7 @@ pub(crate) fn instantiate_if_expression( let ty_to_check = if r#else.is_some() { type_annotation } else { - insert_type(TypeInfo::Tuple(vec![])) + type_engine.insert_type(TypeInfo::Tuple(vec![])) }; let (mut new_warnings, new_errors) = unify_with_self( then.return_type, @@ -60,7 +61,7 @@ pub(crate) fn instantiate_if_expression( let r#else_ret_ty = r#else .as_ref() .map(|x| x.return_type) - .unwrap_or_else(|| insert_type(TypeInfo::Tuple(Vec::new()))); + .unwrap_or_else(|| type_engine.insert_type(TypeInfo::Tuple(Vec::new()))); // if there is a type annotation, then the else branch must exist if !else_deterministically_aborts && !then_deterministically_aborts { let (mut new_warnings, new_errors) = unify_with_self( 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 34fdbc1321e..085ef4b84f7 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 @@ -12,6 +12,7 @@ use sway_types::{state::StateIndex, Span}; #[allow(clippy::too_many_arguments)] pub(crate) fn type_check_method_application( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, method_name_binding: TypeBinding, contract_call_params: Vec, arguments: Vec, @@ -26,10 +27,10 @@ pub(crate) fn type_check_method_application( let ctx = ctx .by_ref() .with_help_text("") - .with_type_annotation(insert_type(TypeInfo::Unknown)); + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); args_buf.push_back(check!( - TypedExpression::type_check(ctx, arg.clone()), - error_recovery_expr(span.clone()), + TypedExpression::type_check(ctx, type_engine, arg.clone()), + error_recovery_expr(type_engine, span.clone()), warnings, errors )); @@ -37,7 +38,12 @@ pub(crate) fn type_check_method_application( // resolve the method name to a typed function declaration and type_check let method = check!( - resolve_method_name(ctx.by_ref(), &method_name_binding, args_buf.clone()), + resolve_method_name( + ctx.by_ref(), + type_engine, + &method_name_binding, + args_buf.clone() + ), return err(warnings, errors), warnings, errors @@ -84,9 +90,11 @@ pub(crate) fn type_check_method_application( let type_annotation = match param.name.span().as_str() { constants::CONTRACT_CALL_GAS_PARAMETER_NAME | constants::CONTRACT_CALL_COINS_PARAMETER_NAME => { - insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)) + type_engine.insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)) + } + constants::CONTRACT_CALL_ASSET_ID_PARAMETER_NAME => { + type_engine.insert_type(TypeInfo::B256) } - constants::CONTRACT_CALL_ASSET_ID_PARAMETER_NAME => insert_type(TypeInfo::B256), _ => unreachable!(), }; let ctx = ctx @@ -100,8 +108,8 @@ pub(crate) fn type_check_method_application( contract_call_params_map.insert( param.name.to_string(), check!( - TypedExpression::type_check(ctx, param.value), - error_recovery_expr(span.clone()), + TypedExpression::type_check(ctx, type_engine, param.value), + error_recovery_expr(type_engine, span.clone()), warnings, errors ), @@ -311,6 +319,7 @@ pub(crate) fn type_check_method_application( pub(crate) fn resolve_method_name( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, method_name: &TypeBinding, arguments: VecDeque, ) -> CompileResult { @@ -325,8 +334,8 @@ pub(crate) fn resolve_method_name( } => { // type check the call path let type_id = check!( - call_path_binding.type_check_with_type_info(&mut ctx), - insert_type(TypeInfo::ErrorRecovery), + call_path_binding.type_check_with_type_info(&mut ctx, type_engine), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors ); @@ -345,6 +354,7 @@ pub(crate) fn resolve_method_name( // find the method check!( ctx.namespace.find_method_for_type( + type_engine, type_id, &type_info_prefix, method_name, @@ -364,11 +374,12 @@ pub(crate) fn resolve_method_name( let type_id = arguments .get(0) .map(|x| x.return_type) - .unwrap_or_else(|| insert_type(TypeInfo::Unknown)); + .unwrap_or_else(|| type_engine.insert_type(TypeInfo::Unknown)); // find the method check!( ctx.namespace.find_method_for_type( + type_engine, type_id, &module_path, &call_path.suffix, @@ -388,11 +399,12 @@ pub(crate) fn resolve_method_name( let type_id = arguments .get(0) .map(|x| x.return_type) - .unwrap_or_else(|| insert_type(TypeInfo::Unknown)); + .unwrap_or_else(|| type_engine.insert_type(TypeInfo::Unknown)); // find the method check!( ctx.namespace.find_method_for_type( + type_engine, type_id, &module_path, method_name, diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/unsafe_downcast.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/unsafe_downcast.rs index c38503252b4..30fdc5b609d 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/unsafe_downcast.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression/unsafe_downcast.rs @@ -5,7 +5,7 @@ use crate::{ ast_node::expression::match_expression::MatchReqMap, IsConstant, TypedEnumVariant, TypedExpressionVariant, }, - type_system::{insert_type, IntegerBits}, + type_system::{IntegerBits, TypeEngine}, Literal, TypeInfo, }; @@ -13,6 +13,7 @@ use super::TypedExpression; // currently the unsafe downcast expr is only used for enums, so this method is specialized for enums pub(crate) fn instantiate_unsafe_downcast( + type_engine: &TypeEngine, exp: &TypedExpression, variant: TypedEnumVariant, span: Span, @@ -22,13 +23,13 @@ pub(crate) fn instantiate_unsafe_downcast( expression: TypedExpressionVariant::EnumTag { exp: Box::new(exp.clone()), }, - return_type: insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)), + return_type: type_engine.insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)), is_constant: IsConstant::No, span: exp.span.clone(), }, TypedExpression { expression: TypedExpressionVariant::Literal(Literal::U64(variant.tag as u64)), - return_type: insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)), + return_type: type_engine.insert_type(TypeInfo::UnsignedInteger(IntegerBits::SixtyFour)), is_constant: IsConstant::No, span: exp.span.clone(), }, diff --git a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression_variant.rs b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression_variant.rs index 40c0137ca1a..d611ba124af 100644 --- a/sway-core/src/semantic_analysis/ast_node/expression/typed_expression_variant.rs +++ b/sway-core/src/semantic_analysis/ast_node/expression/typed_expression_variant.rs @@ -325,7 +325,7 @@ impl PartialEq for TypedExpressionVariant { } impl CopyTypes for TypedExpressionVariant { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { use TypedExpressionVariant::*; match self { Literal(..) => (), @@ -336,25 +336,29 @@ impl CopyTypes for TypedExpressionVariant { } => { arguments .iter_mut() - .for_each(|(_ident, expr)| expr.copy_types(type_mapping)); - function_decl.copy_types(type_mapping); + .for_each(|(_ident, expr)| expr.copy_types(type_engine, type_mapping)); + function_decl.copy_types(type_engine, type_mapping); } LazyOperator { lhs, rhs, .. } => { - (*lhs).copy_types(type_mapping); - (*rhs).copy_types(type_mapping); + (*lhs).copy_types(type_engine, type_mapping); + (*rhs).copy_types(type_engine, type_mapping); } VariableExpression { .. } => (), - Tuple { fields } => fields.iter_mut().for_each(|x| x.copy_types(type_mapping)), - Array { contents } => contents.iter_mut().for_each(|x| x.copy_types(type_mapping)), + Tuple { fields } => fields + .iter_mut() + .for_each(|x| x.copy_types(type_engine, type_mapping)), + Array { contents } => contents + .iter_mut() + .for_each(|x| x.copy_types(type_engine, type_mapping)), ArrayIndex { prefix, index } => { - (*prefix).copy_types(type_mapping); - (*index).copy_types(type_mapping); - } - StructExpression { fields, .. } => { - fields.iter_mut().for_each(|x| x.copy_types(type_mapping)) + (*prefix).copy_types(type_engine, type_mapping); + (*index).copy_types(type_engine, type_mapping); } + StructExpression { fields, .. } => fields + .iter_mut() + .for_each(|x| x.copy_types(type_engine, type_mapping)), CodeBlock(block) => { - block.copy_types(type_mapping); + block.copy_types(type_engine, type_mapping); } FunctionParameter => (), IfExp { @@ -362,10 +366,10 @@ impl CopyTypes for TypedExpressionVariant { then, r#else, } => { - condition.copy_types(type_mapping); - then.copy_types(type_mapping); + condition.copy_types(type_engine, type_mapping); + then.copy_types(type_engine, type_mapping); if let Some(ref mut r#else) = r#else { - r#else.copy_types(type_mapping); + r#else.copy_types(type_engine, type_mapping); } } AsmExpression { @@ -374,7 +378,7 @@ impl CopyTypes for TypedExpressionVariant { } => { registers .iter_mut() - .for_each(|x| x.copy_types(type_mapping)); + .for_each(|x| x.copy_types(type_engine, type_mapping)); } // like a variable expression but it has multiple parts, // like looking up a field in a struct @@ -384,40 +388,44 @@ impl CopyTypes for TypedExpressionVariant { ref mut resolved_type_of_parent, .. } => { - resolved_type_of_parent.update_type(type_mapping, &field_to_access.span); - field_to_access.copy_types(type_mapping); - prefix.copy_types(type_mapping); + resolved_type_of_parent.update_type( + type_engine, + type_mapping, + &field_to_access.span, + ); + field_to_access.copy_types(type_engine, type_mapping); + prefix.copy_types(type_engine, type_mapping); } TupleElemAccess { prefix, ref mut resolved_type_of_parent, .. } => { - resolved_type_of_parent.update_type(type_mapping, &prefix.span); - prefix.copy_types(type_mapping); + resolved_type_of_parent.update_type(type_engine, type_mapping, &prefix.span); + prefix.copy_types(type_engine, type_mapping); } EnumInstantiation { enum_decl, contents, .. } => { - enum_decl.copy_types(type_mapping); + enum_decl.copy_types(type_engine, type_mapping); if let Some(ref mut contents) = contents { - contents.copy_types(type_mapping) + contents.copy_types(type_engine, type_mapping) }; } - AbiCast { address, .. } => address.copy_types(type_mapping), + AbiCast { address, .. } => address.copy_types(type_engine, type_mapping), // storage is never generic and cannot be monomorphized StorageAccess { .. } => (), IntrinsicFunction(kind) => { - kind.copy_types(type_mapping); + kind.copy_types(type_engine, type_mapping); } EnumTag { exp } => { - exp.copy_types(type_mapping); + exp.copy_types(type_engine, type_mapping); } UnsafeDowncast { exp, variant } => { - exp.copy_types(type_mapping); - variant.copy_types(type_mapping); + exp.copy_types(type_engine, type_mapping); + variant.copy_types(type_engine, type_mapping); } AbiName(_) => (), } @@ -563,9 +571,9 @@ impl PartialEq for TypedAsmRegisterDeclaration { } impl CopyTypes for TypedAsmRegisterDeclaration { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { if let Some(ref mut initializer) = self.initializer { - initializer.copy_types(type_mapping) + initializer.copy_types(type_engine, type_mapping) } } } diff --git a/sway-core/src/semantic_analysis/ast_node/mod.rs b/sway-core/src/semantic_analysis/ast_node/mod.rs index 040c56f9bd8..10cf482df50 100644 --- a/sway-core/src/semantic_analysis/ast_node/mod.rs +++ b/sway-core/src/semantic_analysis/ast_node/mod.rs @@ -92,22 +92,26 @@ impl fmt::Display for TypedAstNode { } impl CopyTypes for TypedAstNode { - fn copy_types(&mut self, type_mapping: &TypeMapping) { + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { match self.content { TypedAstNodeContent::ReturnStatement(ref mut ret_stmt) => { - ret_stmt.copy_types(type_mapping) + ret_stmt.copy_types(type_engine, type_mapping) } TypedAstNodeContent::ImplicitReturnExpression(ref mut exp) => { - exp.copy_types(type_mapping) + exp.copy_types(type_engine, type_mapping) + } + TypedAstNodeContent::Declaration(ref mut decl) => { + decl.copy_types(type_engine, type_mapping) + } + TypedAstNodeContent::Expression(ref mut expr) => { + expr.copy_types(type_engine, type_mapping) } - TypedAstNodeContent::Declaration(ref mut decl) => decl.copy_types(type_mapping), - TypedAstNodeContent::Expression(ref mut expr) => expr.copy_types(type_mapping), TypedAstNodeContent::WhileLoop(TypedWhileLoop { ref mut condition, ref mut body, }) => { - condition.copy_types(type_mapping); - body.copy_types(type_mapping); + condition.copy_types(type_engine, type_mapping); + body.copy_types(type_engine, type_mapping); } TypedAstNodeContent::SideEffect => (), } @@ -214,7 +218,11 @@ impl TypedAstNode { } } - pub(crate) fn type_check(mut ctx: TypeCheckContext, node: AstNode) -> CompileResult { + pub(crate) fn type_check( + mut ctx: TypeCheckContext, + type_engine: &TypeEngine, + node: AstNode, + ) -> CompileResult { let mut warnings = Vec::new(); let mut errors = Vec::new(); @@ -223,12 +231,13 @@ impl TypedAstNode { |mut ctx: TypeCheckContext, type_ascription: TypeInfo, expr| { let type_id = check!( ctx.resolve_type_with_self( - insert_type(type_ascription), + type_engine, + type_engine.insert_type(type_ascription), &node.span, EnforceTypeArguments::No, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); @@ -236,7 +245,7 @@ impl TypedAstNode { "This declaration's type annotation does not match up with the assigned \ expression's type.", ); - TypedExpression::type_check(ctx, expr) + TypedExpression::type_check(ctx, type_engine, expr) }; let node = TypedAstNode { @@ -249,8 +258,12 @@ impl TypedAstNode { }; let mut res = match a.import_type { ImportType::Star => ctx.namespace.star_import(&path), - ImportType::SelfImport => ctx.namespace.self_import(&path, a.alias), - ImportType::Item(s) => ctx.namespace.item_import(&path, &s, a.alias), + ImportType::SelfImport => { + ctx.namespace.self_import(type_engine, &path, a.alias) + } + ImportType::Item(s) => { + ctx.namespace.item_import(type_engine, &path, &s, a.alias) + } }; warnings.append(&mut res.warnings); errors.append(&mut res.errors); @@ -270,12 +283,13 @@ impl TypedAstNode { type_ascription_span.unwrap_or_else(|| name.span()); let type_ascription = check!( ctx.resolve_type_with_self( - insert_type(type_ascription), + type_engine, + type_engine.insert_type(type_ascription), &type_ascription_span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors ); @@ -283,9 +297,14 @@ impl TypedAstNode { "Variable declaration's type annotation does not match up \ with the assigned expression's type.", ); - let result = TypedExpression::type_check(ctx.by_ref(), body); - let body = - check!(result, error_recovery_expr(name.span()), warnings, errors); + let result = + TypedExpression::type_check(ctx.by_ref(), type_engine, body); + let body = check!( + result, + error_recovery_expr(type_engine, name.span()), + warnings, + errors + ); let typed_var_decl = TypedDeclaration::VariableDeclaration(TypedVariableDeclaration { name: name.clone(), @@ -305,8 +324,12 @@ impl TypedAstNode { let result = type_check_ascribed_expr(ctx.by_ref(), type_ascription, value); is_screaming_snake_case(&name).ok(&mut warnings, &mut errors); - let value = - check!(result, error_recovery_expr(name.span()), warnings, errors); + let value = check!( + result, + error_recovery_expr(type_engine, name.span()), + warnings, + errors + ); let typed_const_decl = TypedDeclaration::ConstantDeclaration(TypedConstantDeclaration { name: name.clone(), @@ -318,7 +341,7 @@ impl TypedAstNode { } Declaration::EnumDeclaration(decl) => { let enum_decl = check!( - TypedEnumDeclaration::type_check(ctx.by_ref(), decl), + TypedEnumDeclaration::type_check(ctx.by_ref(), type_engine, decl), return err(warnings, errors), warnings, errors @@ -334,10 +357,15 @@ impl TypedAstNode { decl } Declaration::FunctionDeclaration(fn_decl) => { - let mut ctx = ctx.with_type_annotation(insert_type(TypeInfo::Unknown)); + let mut ctx = ctx + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)); let fn_decl = check!( - TypedFunctionDeclaration::type_check(ctx.by_ref(), fn_decl.clone()), - error_recovery_function_declaration(fn_decl), + TypedFunctionDeclaration::type_check( + ctx.by_ref(), + type_engine, + fn_decl.clone() + ), + error_recovery_function_declaration(type_engine, fn_decl), warnings, errors ); @@ -348,7 +376,11 @@ impl TypedAstNode { } Declaration::TraitDeclaration(trait_decl) => { let trait_decl = check!( - TypedTraitDeclaration::type_check(ctx.by_ref(), trait_decl), + TypedTraitDeclaration::type_check( + ctx.by_ref(), + type_engine, + trait_decl + ), return err(warnings, errors), warnings, errors @@ -360,10 +392,10 @@ impl TypedAstNode { } Declaration::Reassignment(Reassignment { lhs, rhs, span }) => { let ctx = ctx - .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)) .with_help_text(""); check!( - reassignment(ctx, lhs, rhs, span), + reassignment(type_engine, ctx, lhs, rhs, span), return err(warnings, errors), warnings, errors @@ -371,7 +403,11 @@ impl TypedAstNode { } Declaration::ImplTrait(impl_trait) => { let (impl_trait, implementing_for_type_id) = check!( - TypedImplTrait::type_check_impl_trait(ctx.by_ref(), impl_trait), + TypedImplTrait::type_check_impl_trait( + ctx.by_ref(), + type_engine, + impl_trait + ), return err(warnings, errors), warnings, errors @@ -385,7 +421,11 @@ impl TypedAstNode { } Declaration::ImplSelf(impl_self) => { let impl_trait = check!( - TypedImplTrait::type_check_impl_self(ctx.by_ref(), impl_self), + TypedImplTrait::type_check_impl_self( + ctx.by_ref(), + type_engine, + impl_self + ), return err(warnings, errors), warnings, errors @@ -399,7 +439,7 @@ impl TypedAstNode { } Declaration::StructDeclaration(decl) => { let decl = check!( - TypedStructDeclaration::type_check(ctx.by_ref(), decl), + TypedStructDeclaration::type_check(ctx.by_ref(), type_engine, decl), return err(warnings, errors), warnings, errors @@ -417,7 +457,11 @@ impl TypedAstNode { } Declaration::AbiDeclaration(abi_decl) => { let abi_decl = check!( - TypedAbiDeclaration::type_check(ctx.by_ref(), abi_decl), + TypedAbiDeclaration::type_check( + ctx.by_ref(), + type_engine, + abi_decl + ), return err(warnings, errors), warnings, errors @@ -437,7 +481,8 @@ impl TypedAstNode { { let type_id = check!( ctx.resolve_type_without_self( - insert_type(type_info), + type_engine, + type_engine.insert_type(type_info), &name.span(), None ), @@ -448,7 +493,11 @@ impl TypedAstNode { let mut ctx = ctx.by_ref().with_type_annotation(type_id); let initializer = check!( - TypedExpression::type_check(ctx.by_ref(), initializer), + TypedExpression::type_check( + ctx.by_ref(), + type_engine, + initializer + ), return err(warnings, errors), warnings, errors, @@ -480,11 +529,11 @@ impl TypedAstNode { } AstNodeContent::Expression(expr) => { let ctx = ctx - .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)) .with_help_text(""); let inner = check!( - TypedExpression::type_check(ctx, expr.clone()), - error_recovery_expr(expr.span()), + TypedExpression::type_check(ctx, type_engine, expr.clone()), + error_recovery_expr(type_engine, expr.span()), warnings, errors ); @@ -500,7 +549,7 @@ impl TypedAstNode { // That is impossible here, as we don't have that information. It // is the responsibility of the function declaration to type check // all return statements contained within it. - .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)) .with_help_text( "Returned value must match up with the function return type \ annotation.", @@ -508,8 +557,8 @@ impl TypedAstNode { TypedAstNodeContent::ReturnStatement(TypedReturnStatement { expr: check!( - TypedExpression::type_check(ctx, expr.clone()), - error_recovery_expr(expr.span()), + TypedExpression::type_check(ctx, type_engine, expr.clone()), + error_recovery_expr(type_engine, expr.span()), warnings, errors ), @@ -519,8 +568,8 @@ impl TypedAstNode { let ctx = ctx.with_help_text("Implicit return must match up with block's type."); let typed_expr = check!( - TypedExpression::type_check(ctx, expr.clone()), - error_recovery_expr(expr.span()), + TypedExpression::type_check(ctx, type_engine, expr.clone()), + error_recovery_expr(type_engine, expr.span()), warnings, errors ); @@ -530,12 +579,12 @@ impl TypedAstNode { let typed_condition = { let ctx = ctx .by_ref() - .with_type_annotation(insert_type(TypeInfo::Boolean)) + .with_type_annotation(type_engine.insert_type(TypeInfo::Boolean)) .with_help_text( "A while loop's loop condition must be a boolean expression.", ); check!( - TypedExpression::type_check(ctx, condition), + TypedExpression::type_check(ctx, type_engine, condition), return err(warnings, errors), warnings, errors @@ -543,17 +592,17 @@ impl TypedAstNode { }; let ctx = ctx - .with_type_annotation(insert_type(TypeInfo::Tuple(Vec::new()))) + .with_type_annotation(type_engine.insert_type(TypeInfo::Tuple(Vec::new()))) .with_help_text( "A while loop's loop body cannot implicitly return a value. Try \ assigning it to a mutable variable declared outside of the loop \ instead.", ); let (typed_body, _block_implicit_return) = check!( - TypedCodeBlock::type_check(ctx, body), + TypedCodeBlock::type_check(ctx, type_engine, body), ( TypedCodeBlock { contents: vec![] }, - insert_type(TypeInfo::Tuple(Vec::new())) + type_engine.insert_type(TypeInfo::Tuple(Vec::new())) ), warnings, errors @@ -588,6 +637,7 @@ impl TypedAstNode { } fn reassignment( + type_engine: &TypeEngine, ctx: TypeCheckContext, lhs: ReassignmentTarget, rhs: Expression, @@ -649,7 +699,8 @@ fn reassignment( }; let names_vec = names_vec.into_iter().rev().collect::>(); let (ty_of_field, _ty_of_parent) = check!( - ctx.namespace.find_subfield_type(&base_name, &names_vec), + ctx.namespace + .find_subfield_type(type_engine, &base_name, &names_vec), return err(warnings, errors), warnings, errors @@ -657,8 +708,8 @@ fn reassignment( // type check the reassignment let ctx = ctx.with_type_annotation(ty_of_field).with_help_text(""); let rhs = check!( - TypedExpression::type_check(ctx, rhs), - error_recovery_expr(span), + TypedExpression::type_check(ctx, type_engine, rhs), + error_recovery_expr(type_engine, span), warnings, errors ); @@ -676,15 +727,16 @@ fn reassignment( } ReassignmentTarget::StorageField(fields) => { let ctx = ctx - .with_type_annotation(insert_type(TypeInfo::Unknown)) + .with_type_annotation(type_engine.insert_type(TypeInfo::Unknown)) .with_help_text(""); - reassign_storage_subfield(ctx, fields, rhs, span) + reassign_storage_subfield(ctx, type_engine, fields, rhs, span) .map(TypedDeclaration::StorageReassignment) } } } fn type_check_interface_surface( + type_engine: &TypeEngine, interface_surface: Vec, namespace: &mut Namespace, ) -> CompileResult> { @@ -716,13 +768,14 @@ fn type_check_interface_surface( is_mutable, type_id: check!( namespace.resolve_type_with_self( + type_engine, type_id, - insert_type(TypeInfo::SelfType), + type_engine.insert_type(TypeInfo::SelfType), &type_span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ), @@ -732,13 +785,14 @@ fn type_check_interface_surface( .collect(), return_type: check!( namespace.resolve_type_with_self( - insert_type(return_type), - insert_type(TypeInfo::SelfType), + type_engine, + type_engine.insert_type(return_type), + type_engine.insert_type(TypeInfo::SelfType), &return_type_span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ), @@ -750,6 +804,7 @@ fn type_check_interface_surface( fn type_check_trait_methods( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, methods: Vec, ) -> CompileResult> { let mut warnings = vec![]; @@ -768,19 +823,22 @@ fn type_check_trait_methods( } in methods { // A context while checking the signature where `self_type` refers to `SelfType`. - let mut sig_ctx = ctx.by_ref().with_self_type(insert_type(TypeInfo::SelfType)); + let mut sig_ctx = ctx + .by_ref() + .with_self_type(type_engine.insert_type(TypeInfo::SelfType)); parameters.clone().into_iter().for_each( |FunctionParameter { name, ref type_id, .. }| { let r#type = check!( sig_ctx.resolve_type_with_self( + type_engine, *type_id, &name.span(), EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); @@ -854,12 +912,13 @@ fn type_check_trait_methods( is_mutable, type_id: check!( sig_ctx.resolve_type_with_self( + type_engine, type_id, &type_span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ), @@ -872,12 +931,13 @@ fn type_check_trait_methods( // TODO check code block implicit return let return_type = check!( ctx.resolve_type_with_self( - insert_type(return_type), + type_engine, + type_engine.insert_type(return_type), &return_type_span, EnforceTypeArguments::Yes, None ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors, ); @@ -890,7 +950,7 @@ fn type_check_trait_methods( annotation.", ); let (body, _code_block_implicit_return) = check!( - TypedCodeBlock::type_check(ctx, body), + TypedCodeBlock::type_check(ctx, type_engine, body), continue, warnings, errors @@ -916,7 +976,10 @@ fn type_check_trait_methods( /// Used to create a stubbed out function when the function fails to compile, preventing cascading /// namespace errors -fn error_recovery_function_declaration(decl: FunctionDeclaration) -> TypedFunctionDeclaration { +fn error_recovery_function_declaration( + type_engine: &TypeEngine, + decl: FunctionDeclaration, +) -> TypedFunctionDeclaration { let FunctionDeclaration { name, return_type, @@ -936,7 +999,7 @@ fn error_recovery_function_declaration(decl: FunctionDeclaration) -> TypedFuncti return_type_span, parameters: Default::default(), visibility, - return_type: insert_type(return_type), + return_type: type_engine.insert_type(return_type), type_parameters: Default::default(), } } @@ -988,6 +1051,7 @@ impl PartialEq for TypeCheckedStorageReassignDescriptor { fn reassign_storage_subfield( ctx: TypeCheckContext, + type_engine: &TypeEngine, fields: Vec, rhs: Expression, span: Span, @@ -1079,8 +1143,8 @@ fn reassign_storage_subfield( } let ctx = ctx.with_type_annotation(curr_type).with_help_text(""); let rhs = check!( - TypedExpression::type_check(ctx, rhs), - error_recovery_expr(span), + TypedExpression::type_check(ctx, type_engine, rhs), + error_recovery_expr(type_engine, span), warnings, errors ); diff --git a/sway-core/src/semantic_analysis/ast_node/return_statement.rs b/sway-core/src/semantic_analysis/ast_node/return_statement.rs index 55e61f3321b..3646251de9d 100644 --- a/sway-core/src/semantic_analysis/ast_node/return_statement.rs +++ b/sway-core/src/semantic_analysis/ast_node/return_statement.rs @@ -1,3 +1,5 @@ +use crate::type_system::TypeEngine; + use super::{CopyTypes, TypeMapping, TypedExpression}; #[derive(Clone, Debug, Eq, PartialEq)] @@ -7,7 +9,7 @@ pub struct TypedReturnStatement { impl CopyTypes for TypedReturnStatement { /// Makes a fresh copy of all types contained in this statement. - fn copy_types(&mut self, type_mapping: &TypeMapping) { - self.expr.copy_types(type_mapping); + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { + self.expr.copy_types(type_engine, type_mapping); } } diff --git a/sway-core/src/semantic_analysis/module.rs b/sway-core/src/semantic_analysis/module.rs index 51ebf3ed618..2f5023a7bf3 100644 --- a/sway-core/src/semantic_analysis/module.rs +++ b/sway-core/src/semantic_analysis/module.rs @@ -19,13 +19,18 @@ impl TypedModule { /// Type-check the given parsed module to produce a typed module. /// /// Recursively type-checks submodules first. - pub fn type_check(mut ctx: TypeCheckContext, parsed: &ParseModule) -> CompileResult { + pub fn type_check( + mut ctx: TypeCheckContext, + type_engine: &TypeEngine, + parsed: &ParseModule, + ) -> CompileResult { let ParseModule { submodules, tree } = parsed; // Type-check submodules first in order of declaration. let mut submodules_res = ok(vec![], vec![], vec![]); for (name, submodule) in submodules { - let submodule_res = TypedSubmodule::type_check(ctx.by_ref(), name.clone(), submodule); + let submodule_res = + TypedSubmodule::type_check(ctx.by_ref(), type_engine, name.clone(), submodule); submodules_res = submodules_res.flat_map(|mut submodules| { submodule_res.map(|submodule| { submodules.push((name.clone(), submodule)); @@ -38,8 +43,9 @@ impl TypedModule { let ordered_nodes_res = node_dependencies::order_ast_nodes_by_dependency(tree.root_nodes.clone()); - let typed_nodes_res = ordered_nodes_res - .flat_map(|ordered_nodes| Self::type_check_nodes(ctx.by_ref(), ordered_nodes)); + let typed_nodes_res = ordered_nodes_res.flat_map(|ordered_nodes| { + Self::type_check_nodes(ctx.by_ref(), type_engine, ordered_nodes) + }); let validated_nodes_res = typed_nodes_res.flat_map(|typed_nodes| { let errors = check_supertraits(&typed_nodes, ctx.namespace); @@ -57,13 +63,14 @@ impl TypedModule { fn type_check_nodes( mut ctx: TypeCheckContext, + type_engine: &TypeEngine, nodes: Vec, ) -> CompileResult> { let mut warnings = Vec::new(); let mut errors = Vec::new(); let typed_nodes = nodes .into_iter() - .map(|node| TypedAstNode::type_check(ctx.by_ref(), node)) + .map(|node| TypedAstNode::type_check(ctx.by_ref(), type_engine, node)) .filter_map(|res| res.ok(&mut warnings, &mut errors)) .collect(); @@ -78,6 +85,7 @@ impl TypedModule { impl TypedSubmodule { pub fn type_check( parent_ctx: TypeCheckContext, + type_engine: &TypeEngine, dep_name: DepName, submodule: &ParseSubmodule, ) -> CompileResult { @@ -85,8 +93,8 @@ impl TypedSubmodule { library_name, module, } = submodule; - parent_ctx.enter_submodule(dep_name, |submod_ctx| { - let module_res = TypedModule::type_check(submod_ctx, module); + parent_ctx.enter_submodule(type_engine, dep_name, |submod_ctx| { + let module_res = TypedModule::type_check(submod_ctx, type_engine, module); module_res.map(|module| TypedSubmodule { library_name: library_name.clone(), module, diff --git a/sway-core/src/semantic_analysis/namespace/items.rs b/sway-core/src/semantic_analysis/namespace/items.rs index 8b9cc2704ed..9ea0acdcc32 100644 --- a/sway-core/src/semantic_analysis/namespace/items.rs +++ b/sway-core/src/semantic_analysis/namespace/items.rs @@ -128,10 +128,11 @@ impl Items { pub(crate) fn get_methods_for_type( &self, + type_engine: &TypeEngine, implementing_for_type_id: TypeId, ) -> Vec { self.implemented_traits - .get_methods_for_type(implementing_for_type_id) + .get_methods_for_type(type_engine, implementing_for_type_id) } pub(crate) fn get_canonical_path(&self, symbol: &Ident) -> &[Ident] { @@ -156,6 +157,7 @@ impl Items { /// the second is the [ResolvedType] of its parent, for control-flow analysis. pub(crate) fn find_subfield_type( &self, + type_engine: &TypeEngine, base_name: &Ident, projections: &[ProjectionKind], ) -> CompileResult<(TypeId, TypeId)> { @@ -171,7 +173,7 @@ impl Items { } }; let mut symbol = check!( - symbol.return_type(), + symbol.return_type(type_engine), return err(warnings, errors), warnings, errors diff --git a/sway-core/src/semantic_analysis/namespace/module.rs b/sway-core/src/semantic_analysis/namespace/module.rs index f06585d0c6c..21fa1ae4c1d 100644 --- a/sway-core/src/semantic_analysis/namespace/module.rs +++ b/sway-core/src/semantic_analysis/namespace/module.rs @@ -2,6 +2,7 @@ use crate::{ error::*, parse_tree::Visibility, semantic_analysis::{ast_node::TypedVariableDeclaration, declaration::VariableMutability}, + type_system::TypeEngine, CompileResult, Ident, TypedDeclaration, }; @@ -123,12 +124,13 @@ impl Module { /// import. pub(crate) fn self_import( &mut self, + type_engine: &TypeEngine, src: &Path, dst: &Path, alias: Option, ) -> CompileResult<()> { let (last_item, src) = src.split_last().expect("guaranteed by grammar"); - self.item_import(src, last_item, dst, alias) + self.item_import(type_engine, src, last_item, dst, alias) } /// Pull a single `item` from the given `src` module and import it into the `dst` module. @@ -136,6 +138,7 @@ impl Module { /// Paths are assumed to be relative to `self`. pub(crate) fn item_import( &mut self, + type_engine: &TypeEngine, src: &Path, item: &Ident, dst: &Path, @@ -165,7 +168,7 @@ impl Module { self[dst].insert_symbol(alias.unwrap_or_else(|| name.clone()), decl.clone()); return ok((), warnings, errors); } - let a = decl.return_type().value; + let a = decl.return_type(type_engine).value; // if this is an enum or struct, import its implementations let mut res = match a { Some(a) => src_ns.implemented_traits.get_call_path_and_type_info(a), diff --git a/sway-core/src/semantic_analysis/namespace/namespace.rs b/sway-core/src/semantic_analysis/namespace/namespace.rs index 9eb79eec999..af9eb91d6b1 100644 --- a/sway-core/src/semantic_analysis/namespace/namespace.rs +++ b/sway-core/src/semantic_analysis/namespace/namespace.rs @@ -100,6 +100,7 @@ impl Namespace { /// Short-hand for calling [Root::resolve_type_with_self] on `root` with the `mod_path`. pub(crate) fn resolve_type_with_self( &mut self, + type_engine: &TypeEngine, type_id: TypeId, self_type: TypeId, span: &Span, @@ -107,6 +108,7 @@ impl Namespace { type_info_prefix: Option<&Path>, ) -> CompileResult { self.root.resolve_type_with_self( + type_engine, type_id, self_type, span, @@ -119,11 +121,13 @@ impl Namespace { /// Short-hand for calling [Root::resolve_type_without_self] on `root` and with the `mod_path`. pub(crate) fn resolve_type_without_self( &mut self, + type_engine: &TypeEngine, type_id: TypeId, span: &Span, type_info_prefix: Option<&Path>, ) -> CompileResult { self.root.resolve_type( + type_engine, type_id, span, EnforceTypeArguments::Yes, @@ -135,6 +139,7 @@ impl Namespace { /// Short-hand for calling [Root::find_method_for_type] on `root` with the `mod_path`. pub(crate) fn find_method_for_type( &mut self, + type_engine: &TypeEngine, r#type: TypeId, method_prefix: &Path, method_name: &Ident, @@ -142,6 +147,7 @@ impl Namespace { args_buf: &VecDeque, ) -> CompileResult { self.root.find_method_for_type( + type_engine, &self.mod_path, r#type, method_prefix, @@ -157,18 +163,26 @@ impl Namespace { } /// Short-hand for performing a [Module::self_import] with `mod_path` as the destination. - pub(crate) fn self_import(&mut self, src: &Path, alias: Option) -> CompileResult<()> { - self.root.self_import(src, &self.mod_path, alias) + pub(crate) fn self_import( + &mut self, + type_engine: &TypeEngine, + src: &Path, + alias: Option, + ) -> CompileResult<()> { + self.root + .self_import(type_engine, src, &self.mod_path, alias) } /// Short-hand for performing a [Module::item_import] with `mod_path` as the destination. pub(crate) fn item_import( &mut self, + type_engine: &TypeEngine, src: &Path, item: &Ident, alias: Option, ) -> CompileResult<()> { - self.root.item_import(src, item, &self.mod_path, alias) + self.root + .item_import(type_engine, src, item, &self.mod_path, alias) } /// "Enter" the submodule at the given path by returning a new [SubmoduleNamespace]. diff --git a/sway-core/src/semantic_analysis/namespace/root.rs b/sway-core/src/semantic_analysis/namespace/root.rs index b415e425da0..274618b8e27 100644 --- a/sway-core/src/semantic_analysis/namespace/root.rs +++ b/sway-core/src/semantic_analysis/namespace/root.rs @@ -64,8 +64,10 @@ impl Root { }) } + #[allow(clippy::too_many_arguments)] pub(crate) fn resolve_type_with_self( &mut self, + type_engine: &TypeEngine, mut type_id: TypeId, self_type: TypeId, span: &Span, @@ -75,6 +77,7 @@ impl Root { ) -> CompileResult { type_id.replace_self_type(self_type); self.resolve_type( + type_engine, type_id, span, enforce_type_arguments, @@ -85,6 +88,7 @@ impl Root { pub(crate) fn resolve_type( &self, + type_engine: &TypeEngine, type_id: TypeId, span: &Span, enforce_type_arguments: EnforceTypeArguments, @@ -121,7 +125,7 @@ impl Root { warnings, errors ); - decl.create_type_id() + decl.create_type_id(type_engine) } Some(TypedDeclaration::EnumDeclaration(mut decl)) => { check!( @@ -137,48 +141,56 @@ impl Root { warnings, errors ); - decl.create_type_id() + decl.create_type_id(type_engine) } Some(TypedDeclaration::GenericTypeForFunctionScope { name, type_id }) => { - insert_type(TypeInfo::Ref(type_id, name.span())) + type_engine.insert_type(TypeInfo::Ref(type_id, name.span())) } _ => { errors.push(CompileError::UnknownTypeName { name: name.to_string(), span: name.span(), }); - insert_type(TypeInfo::ErrorRecovery) + type_engine.insert_type(TypeInfo::ErrorRecovery) } } } TypeInfo::Ref(id, _) => id, TypeInfo::Array(type_id, n) => { let new_type_id = check!( - self.resolve_type(type_id, span, enforce_type_arguments, None, mod_path), - insert_type(TypeInfo::ErrorRecovery), + self.resolve_type( + type_engine, + type_id, + span, + enforce_type_arguments, + None, + mod_path + ), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors ); - insert_type(TypeInfo::Array(new_type_id, n)) + type_engine.insert_type(TypeInfo::Array(new_type_id, n)) } TypeInfo::Tuple(mut type_arguments) => { for type_argument in type_arguments.iter_mut() { type_argument.type_id = check!( self.resolve_type( + type_engine, type_argument.type_id, span, enforce_type_arguments, None, mod_path ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors ); } - insert_type(TypeInfo::Tuple(type_arguments)) + type_engine.insert_type(TypeInfo::Tuple(type_arguments)) } - o => insert_type(o), + o => type_engine.insert_type(o), }; ok(type_id, warnings, errors) } @@ -191,8 +203,10 @@ impl Root { /// /// This method should only be called on the root namespace. `mod_path` is the current module, /// `method_path` is assumed to be absolute. + #[allow(clippy::too_many_arguments)] pub(crate) fn find_method_for_type( &mut self, + type_engine: &TypeEngine, mod_path: &Path, mut type_id: TypeId, method_prefix: &Path, @@ -212,20 +226,21 @@ impl Root { ); // grab the local methods from the local module - let local_methods = local_module.get_methods_for_type(type_id); + let local_methods = local_module.get_methods_for_type(type_engine, type_id); type_id.replace_self_type(self_type); // resolve the type let type_id = check!( self.resolve_type( + type_engine, type_id, &method_name.span(), EnforceTypeArguments::No, None, method_prefix ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors ); @@ -239,7 +254,7 @@ impl Root { ); // grab the methods from where the type is declared - let mut type_methods = type_module.get_methods_for_type(type_id); + let mut type_methods = type_module.get_methods_for_type(type_engine, type_id); let mut methods = local_methods; methods.append(&mut type_methods); diff --git a/sway-core/src/semantic_analysis/namespace/trait_map.rs b/sway-core/src/semantic_analysis/namespace/trait_map.rs index e359d2329e5..ca40e19214c 100644 --- a/sway-core/src/semantic_analysis/namespace/trait_map.rs +++ b/sway-core/src/semantic_analysis/namespace/trait_map.rs @@ -1,5 +1,5 @@ use crate::{ - type_system::{create_type_mapping, look_up_type_id, CopyTypes, TypeId}, + type_system::{create_type_mapping, look_up_type_id, CopyTypes, TypeEngine, TypeId}, CallPath, TypeInfo, TypedFunctionDeclaration, }; @@ -78,6 +78,7 @@ impl TraitMap { pub(crate) fn get_methods_for_type( &self, + type_engine: &TypeEngine, incoming_type_id: TypeId, ) -> Vec { let mut methods = vec![]; @@ -91,7 +92,7 @@ impl TraitMap { let mut trait_methods = trait_methods.values().cloned().collect::>(); trait_methods .iter_mut() - .for_each(|x| x.copy_types(&type_mapping)); + .for_each(|x| x.copy_types(type_engine, &type_mapping)); methods.append(&mut trait_methods); } } diff --git a/sway-core/src/semantic_analysis/program.rs b/sway-core/src/semantic_analysis/program.rs index dc1961aaa43..e6d08a07d5a 100644 --- a/sway-core/src/semantic_analysis/program.rs +++ b/sway-core/src/semantic_analysis/program.rs @@ -9,7 +9,7 @@ use crate::{ namespace::{self, Namespace}, TypeCheckContext, TypedModule, }, - type_system::*, + type_system::{self, *}, types::ToJsonAbi, }; use fuel_tx::StorageSlot; @@ -30,12 +30,13 @@ impl TypedProgram { pub fn type_check( parsed: &ParseProgram, initial_namespace: namespace::Module, + initial_type_engine: &type_system::TypeEngine, ) -> CompileResult { let mut namespace = Namespace::init_root(initial_namespace); - let ctx = TypeCheckContext::from_root(&mut namespace); + let ctx = TypeCheckContext::from_root(&mut namespace, initial_type_engine); let ParseProgram { root, kind } = parsed; let mod_span = root.tree.span.clone(); - let mod_res = TypedModule::type_check(ctx, root); + let mod_res = TypedModule::type_check(ctx, initial_type_engine, root); mod_res.flat_map(|root| { let kind_res = Self::validate_root(&root, kind.clone(), mod_span); kind_res.map(|kind| Self { diff --git a/sway-core/src/semantic_analysis/type_check_context.rs b/sway-core/src/semantic_analysis/type_check_context.rs index e1c0243c9ff..4c6ba945230 100644 --- a/sway-core/src/semantic_analysis/type_check_context.rs +++ b/sway-core/src/semantic_analysis/type_check_context.rs @@ -3,8 +3,8 @@ use crate::{ parse_tree::declaration::Purity, semantic_analysis::{ast_node::Mode, Namespace}, type_system::{ - insert_type, monomorphize, unify_with_self, CopyTypes, EnforceTypeArguments, - MonomorphizeHelper, TypeArgument, TypeId, TypeInfo, + monomorphize, unify_with_self, CopyTypes, EnforceTypeArguments, MonomorphizeHelper, + TypeArgument, TypeEngine, TypeId, TypeInfo, }, CompileResult, CompileWarning, TypeError, }; @@ -57,17 +57,17 @@ impl<'ns> TypeCheckContext<'ns> { /// - mode: NoneAbi /// - help_text: "" /// - purity: Pure - pub fn from_root(root_namespace: &'ns mut Namespace) -> Self { - Self::from_module_namespace(root_namespace) + pub fn from_root(root_namespace: &'ns mut Namespace, type_engine: &TypeEngine) -> Self { + Self::from_module_namespace(root_namespace, type_engine) } - fn from_module_namespace(namespace: &'ns mut Namespace) -> Self { + fn from_module_namespace(namespace: &'ns mut Namespace, type_engine: &TypeEngine) -> Self { Self { namespace, - type_annotation: insert_type(TypeInfo::Unknown), + type_annotation: type_engine.insert_type(TypeInfo::Unknown), help_text: "", // TODO: Contract? Should this be passed in based on program kind (aka TreeType)? - self_type: insert_type(TypeInfo::Contract), + self_type: type_engine.insert_type(TypeInfo::Contract), mode: Mode::NonAbi, purity: Purity::default(), } @@ -108,7 +108,12 @@ impl<'ns> TypeCheckContext<'ns> { /// type-checking its content. /// /// Returns the result of the given `with_submod_ctx` function. - pub fn enter_submodule(self, dep_name: Ident, with_submod_ctx: F) -> T + pub fn enter_submodule( + self, + type_engine: &TypeEngine, + dep_name: Ident, + with_submod_ctx: F, + ) -> T where F: FnOnce(TypeCheckContext) -> T, { @@ -117,7 +122,7 @@ impl<'ns> TypeCheckContext<'ns> { // engine here once they're added. let Self { namespace, .. } = self; let mut submod_ns = namespace.enter_submodule(dep_name); - let submod_ctx = TypeCheckContext::from_module_namespace(&mut submod_ns); + let submod_ctx = TypeCheckContext::from_module_namespace(&mut submod_ns, type_engine); with_submod_ctx(submod_ctx) } @@ -199,12 +204,14 @@ impl<'ns> TypeCheckContext<'ns> { /// the `TypeCheckContext`. pub(crate) fn resolve_type_with_self( &mut self, + type_engine: &TypeEngine, type_id: TypeId, span: &Span, enforce_type_args: EnforceTypeArguments, type_info_prefix: Option<&Path>, ) -> CompileResult { self.namespace.resolve_type_with_self( + type_engine, type_id, self.self_type, span, @@ -216,12 +223,13 @@ impl<'ns> TypeCheckContext<'ns> { /// Short-hand for calling [Namespace::resolve_type_without_self] pub(crate) fn resolve_type_without_self( &mut self, + type_engine: &TypeEngine, type_id: TypeId, span: &Span, type_info_prefix: Option<&Path>, ) -> CompileResult { self.namespace - .resolve_type_without_self(type_id, span, type_info_prefix) + .resolve_type_without_self(type_engine, type_id, span, type_info_prefix) } /// Short-hand around `type_system::unify_with_self`, where the `TypeCheckContext` provides the diff --git a/sway-core/src/type_system/copy_types.rs b/sway-core/src/type_system/copy_types.rs index 7266b63d9b2..770f69a1e90 100644 --- a/sway-core/src/type_system/copy_types.rs +++ b/sway-core/src/type_system/copy_types.rs @@ -1,5 +1,5 @@ -use super::TypeMapping; +use super::{TypeEngine, TypeMapping}; pub(crate) trait CopyTypes { - fn copy_types(&mut self, type_mapping: &TypeMapping); + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping); } diff --git a/sway-core/src/type_system/create_type_id.rs b/sway-core/src/type_system/create_type_id.rs index 767f450d715..74917f3a5b2 100644 --- a/sway-core/src/type_system/create_type_id.rs +++ b/sway-core/src/type_system/create_type_id.rs @@ -1,5 +1,5 @@ -use crate::type_system::TypeId; +use super::{TypeEngine, TypeId}; pub(crate) trait CreateTypeId { - fn create_type_id(&self) -> TypeId; + fn create_type_id(&self, type_engine: &TypeEngine) -> TypeId; } diff --git a/sway-core/src/type_system/type_argument.rs b/sway-core/src/type_system/type_argument.rs index 18f643527d7..ca56700f4bb 100644 --- a/sway-core/src/type_system/type_argument.rs +++ b/sway-core/src/type_system/type_argument.rs @@ -29,14 +29,14 @@ impl PartialEq for TypeArgument { } } -impl Default for TypeArgument { - fn default() -> Self { - TypeArgument { - type_id: insert_type(TypeInfo::Unknown), - span: Span::dummy(), - } - } -} +// impl Default for TypeArgument { +// fn default() -> Self { +// TypeArgument { +// type_id: insert_type(TypeInfo::Unknown), +// span: Span::dummy(), +// } +// } +// } impl fmt::Display for TypeArgument { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/sway-core/src/type_system/type_binding.rs b/sway-core/src/type_system/type_binding.rs index 252d3e40ca0..b8d9b94009c 100644 --- a/sway-core/src/type_system/type_binding.rs +++ b/sway-core/src/type_system/type_binding.rs @@ -3,11 +3,11 @@ use sway_types::{Span, Spanned}; use crate::{ error::{err, ok}, semantic_analysis::TypeCheckContext, - type_system::{insert_type, EnforceTypeArguments}, + type_system::EnforceTypeArguments, CallPath, CompileResult, TypeInfo, TypedDeclaration, }; -use super::{ReplaceSelfType, TypeArgument, TypeId}; +use super::{ReplaceSelfType, TypeArgument, TypeEngine, TypeId}; /// A `TypeBinding` is the result of using turbofish to bind types to /// generic parameters. @@ -85,6 +85,7 @@ impl TypeBinding> { pub(crate) fn type_check_with_type_info( &self, ctx: &mut TypeCheckContext, + type_engine: &TypeEngine, ) -> CompileResult { let mut warnings = vec![]; let mut errors = vec![]; @@ -111,12 +112,13 @@ impl TypeBinding> { // resolve the type of the type info object let type_id = check!( ctx.resolve_type_with_self( - insert_type(type_info), + type_engine, + type_engine.insert_type(type_info), &type_info_span, EnforceTypeArguments::No, Some(&type_info_prefix) ), - insert_type(TypeInfo::ErrorRecovery), + type_engine.insert_type(TypeInfo::ErrorRecovery), warnings, errors ); diff --git a/sway-core/src/type_system/type_engine.rs b/sway-core/src/type_system/type_engine.rs index 4adffa4e943..cce2487dd09 100644 --- a/sway-core/src/type_system/type_engine.rs +++ b/sway-core/src/type_system/type_engine.rs @@ -10,7 +10,7 @@ lazy_static! { } #[derive(Debug, Default)] -pub(crate) struct TypeEngine { +pub struct TypeEngine { slab: ConcurrentSlab, storage_only_types: ConcurrentSlab, } @@ -71,8 +71,8 @@ impl TypeEngine { }); return err(warnings, errors); } - let type_mapping = insert_type_parameters(value.type_parameters()); - value.copy_types(&type_mapping); + let type_mapping = insert_type_parameters(self, value.type_parameters()); + value.copy_types(self, &type_mapping); ok((), warnings, errors) } (true, false) => { @@ -104,18 +104,19 @@ impl TypeEngine { for type_argument in type_arguments.iter_mut() { type_argument.type_id = check!( namespace.resolve_type( + self, type_argument.type_id, &type_argument.span, enforce_type_arguments, None, mod_path ), - insert_type(TypeInfo::ErrorRecovery), + self.insert_type(TypeInfo::ErrorRecovery), warnings, errors ); } - let type_mapping = insert_type_parameters(value.type_parameters()); + let type_mapping = insert_type_parameters(self, value.type_parameters()); for ((_, interim_type), type_argument) in type_mapping.iter().zip(type_arguments.iter()) { @@ -128,7 +129,7 @@ impl TypeEngine { warnings.append(&mut new_warnings); errors.append(&mut new_errors.into_iter().map(|x| x.into()).collect()); } - value.copy_types(&type_mapping); + value.copy_types(self, &type_mapping); ok((), warnings, errors) } } @@ -477,9 +478,9 @@ impl TypeEngine { } } -pub fn insert_type(ty: TypeInfo) -> TypeId { - TYPE_ENGINE.insert_type(ty) -} +// pub fn insert_type(ty: TypeInfo) -> TypeId { +// TYPE_ENGINE.insert_type(ty) +// } pub fn look_up_type_id(id: TypeId) -> TypeInfo { TYPE_ENGINE.look_up_type_id(id) diff --git a/sway-core/src/type_system/type_id.rs b/sway-core/src/type_system/type_id.rs index 0333eb140ee..c28cb861b28 100644 --- a/sway-core/src/type_system/type_id.rs +++ b/sway-core/src/type_system/type_id.rs @@ -155,12 +155,20 @@ impl ReplaceSelfType for TypeId { } impl TypeId { - pub(crate) fn update_type(&mut self, type_mapping: &TypeMapping, span: &Span) { - *self = match look_up_type_id(*self).matches_type_parameter(type_mapping) { - Some(matching_id) => insert_type(TypeInfo::Ref(matching_id, span.clone())), + pub(crate) fn update_type( + &mut self, + type_engine: &TypeEngine, + mapping: &TypeMapping, + span: &Span, + ) { + *self = match look_up_type_id(*self).matches_type_parameter(type_engine, mapping) { + Some(matching_id) => type_engine.insert_type(TypeInfo::Ref(matching_id, span.clone())), None => { - let ty = TypeInfo::Ref(insert_type(look_up_type_id_raw(*self)), span.clone()); - insert_type(ty) + let ty = TypeInfo::Ref( + type_engine.insert_type(look_up_type_id_raw(*self)), + span.clone(), + ); + type_engine.insert_type(ty) } }; } diff --git a/sway-core/src/type_system/type_info.rs b/sway-core/src/type_system/type_info.rs index 08af68aff27..743bcaaf7db 100644 --- a/sway-core/src/type_system/type_info.rs +++ b/sway-core/src/type_system/type_info.rs @@ -680,7 +680,11 @@ impl TypeInfo { } } - pub(crate) fn matches_type_parameter(&self, mapping: &TypeMapping) -> Option { + pub(crate) fn matches_type_parameter( + &self, + type_engine: &TypeEngine, + mapping: &TypeMapping, + ) -> Option { use TypeInfo::*; match self { TypeInfo::Custom { .. } => { @@ -706,23 +710,23 @@ impl TypeInfo { } => { let mut new_fields = fields.clone(); for new_field in new_fields.iter_mut() { - if let Some(matching_id) = - look_up_type_id(new_field.type_id).matches_type_parameter(mapping) + if let Some(matching_id) = look_up_type_id(new_field.type_id) + .matches_type_parameter(type_engine, mapping) { - new_field.type_id = - insert_type(TypeInfo::Ref(matching_id, new_field.span.clone())); + new_field.type_id = type_engine + .insert_type(TypeInfo::Ref(matching_id, new_field.span.clone())); } } let mut new_type_parameters = type_parameters.clone(); for new_param in new_type_parameters.iter_mut() { - if let Some(matching_id) = - look_up_type_id(new_param.type_id).matches_type_parameter(mapping) + if let Some(matching_id) = look_up_type_id(new_param.type_id) + .matches_type_parameter(type_engine, mapping) { - new_param.type_id = - insert_type(TypeInfo::Ref(matching_id, new_param.span().clone())); + new_param.type_id = type_engine + .insert_type(TypeInfo::Ref(matching_id, new_param.span().clone())); } } - Some(insert_type(TypeInfo::Struct { + Some(type_engine.insert_type(TypeInfo::Struct { fields: new_fields, name: name.clone(), type_parameters: new_type_parameters, @@ -735,41 +739,41 @@ impl TypeInfo { } => { let mut new_variants = variant_types.clone(); for new_variant in new_variants.iter_mut() { - if let Some(matching_id) = - look_up_type_id(new_variant.type_id).matches_type_parameter(mapping) + if let Some(matching_id) = look_up_type_id(new_variant.type_id) + .matches_type_parameter(type_engine, mapping) { - new_variant.type_id = - insert_type(TypeInfo::Ref(matching_id, new_variant.span.clone())); + new_variant.type_id = type_engine + .insert_type(TypeInfo::Ref(matching_id, new_variant.span.clone())); } } let mut new_type_parameters = type_parameters.clone(); for new_param in new_type_parameters.iter_mut() { - if let Some(matching_id) = - look_up_type_id(new_param.type_id).matches_type_parameter(mapping) + if let Some(matching_id) = look_up_type_id(new_param.type_id) + .matches_type_parameter(type_engine, mapping) { - new_param.type_id = - insert_type(TypeInfo::Ref(matching_id, new_param.span().clone())); + new_param.type_id = type_engine + .insert_type(TypeInfo::Ref(matching_id, new_param.span().clone())); } } - Some(insert_type(TypeInfo::Enum { + Some(type_engine.insert_type(TypeInfo::Enum { variant_types: new_variants, type_parameters: new_type_parameters, name: name.clone(), })) } TypeInfo::Array(ary_ty_id, count) => look_up_type_id(*ary_ty_id) - .matches_type_parameter(mapping) - .map(|matching_id| insert_type(TypeInfo::Array(matching_id, *count))), + .matches_type_parameter(type_engine, mapping) + .map(|matching_id| type_engine.insert_type(TypeInfo::Array(matching_id, *count))), TypeInfo::Tuple(fields) => { let mut new_fields = Vec::new(); let mut index = 0; while index < fields.len() { - let new_field_id_opt = - look_up_type_id(fields[index].type_id).matches_type_parameter(mapping); + let new_field_id_opt = look_up_type_id(fields[index].type_id) + .matches_type_parameter(type_engine, mapping); if let Some(new_field_id) = new_field_id_opt { new_fields.extend(fields[..index].iter().cloned()); new_fields.push(TypeArgument { - type_id: insert_type(TypeInfo::Ref( + type_id: type_engine.insert_type(TypeInfo::Ref( new_field_id, fields[index].span.clone(), )), @@ -782,10 +786,10 @@ impl TypeInfo { } while index < fields.len() { let new_field = match look_up_type_id(fields[index].type_id) - .matches_type_parameter(mapping) + .matches_type_parameter(type_engine, mapping) { Some(new_field_id) => TypeArgument { - type_id: insert_type(TypeInfo::Ref( + type_id: type_engine.insert_type(TypeInfo::Ref( new_field_id, fields[index].span.clone(), )), @@ -799,7 +803,7 @@ impl TypeInfo { if new_fields.is_empty() { None } else { - Some(insert_type(TypeInfo::Tuple(new_fields))) + Some(type_engine.insert_type(TypeInfo::Tuple(new_fields))) } } Unknown diff --git a/sway-core/src/type_system/type_mapping.rs b/sway-core/src/type_system/type_mapping.rs index d8ea14b87bd..3fee998002a 100644 --- a/sway-core/src/type_system/type_mapping.rs +++ b/sway-core/src/type_system/type_mapping.rs @@ -2,13 +2,16 @@ use super::*; pub(crate) type TypeMapping = Vec<(TypeId, TypeId)>; -pub(crate) fn insert_type_parameters(type_parameters: &[TypeParameter]) -> TypeMapping { +pub(crate) fn insert_type_parameters( + type_engine: &TypeEngine, + type_parameters: &[TypeParameter], +) -> TypeMapping { type_parameters .iter() .map(|x| { ( x.type_id, - insert_type(TypeInfo::UnknownGeneric { + type_engine.insert_type(TypeInfo::UnknownGeneric { name: x.name_ident.clone(), }), ) diff --git a/sway-core/src/type_system/type_parameter.rs b/sway-core/src/type_system/type_parameter.rs index 414c0e1f134..9ebc47a4f41 100644 --- a/sway-core/src/type_system/type_parameter.rs +++ b/sway-core/src/type_system/type_parameter.rs @@ -42,14 +42,20 @@ impl PartialEq for TypeParameter { } impl CopyTypes for TypeParameter { - fn copy_types(&mut self, type_mapping: &TypeMapping) { - self.type_id = match look_up_type_id(self.type_id).matches_type_parameter(type_mapping) { - Some(matching_id) => insert_type(TypeInfo::Ref(matching_id, self.name_ident.span())), - None => { - let ty = TypeInfo::Ref(insert_type(look_up_type_id_raw(self.type_id)), self.span()); - insert_type(ty) - } - }; + fn copy_types(&mut self, type_engine: &TypeEngine, type_mapping: &TypeMapping) { + self.type_id = + match look_up_type_id(self.type_id).matches_type_parameter(type_engine, type_mapping) { + Some(matching_id) => { + type_engine.insert_type(TypeInfo::Ref(matching_id, self.name_ident.span())) + } + None => { + let ty = TypeInfo::Ref( + type_engine.insert_type(look_up_type_id_raw(self.type_id)), + self.span(), + ); + type_engine.insert_type(ty) + } + }; } } @@ -90,6 +96,7 @@ impl ToJsonAbi for TypeParameter { impl TypeParameter { pub(crate) fn type_check( ctx: TypeCheckContext, + type_engine: &TypeEngine, type_parameter: TypeParameter, ) -> CompileResult { let mut warnings = vec![]; @@ -101,7 +108,7 @@ impl TypeParameter { return err(warnings, errors); } // TODO: add check here to see if the type parameter has a valid name and does not have type parameters - let type_id = insert_type(TypeInfo::UnknownGeneric { + let type_id = type_engine.insert_type(TypeInfo::UnknownGeneric { name: type_parameter.name_ident.clone(), }); let type_parameter_decl = TypedDeclaration::GenericTypeForFunctionScope { diff --git a/sway-fmt/src/fmt.rs b/sway-fmt/src/fmt.rs index 2ad13deb786..eb95b5ea04d 100644 --- a/sway-fmt/src/fmt.rs +++ b/sway-fmt/src/fmt.rs @@ -2,7 +2,7 @@ use super::code_builder::CodeBuilder; use crate::traversal::{traverse_for_changes, Change}; use ropey::Rope; use std::sync::Arc; -use sway_core::BuildConfig; +use sway_core::{type_system::TypeEngine, BuildConfig}; /// Returns number of lines and formatted text. /// Formatting is done as a 2-step process. @@ -15,7 +15,9 @@ pub fn get_formatted_data( formatting_options: FormattingOptions, build_config: Option<&BuildConfig>, ) -> Result<(usize, String), Vec> { - let parsed_res = sway_core::parse(file.clone(), build_config); + // this TypeEngine should not be needed to be used for anything + let type_engine = TypeEngine::default(); + let parsed_res = sway_core::parse(file.clone(), build_config, &type_engine); match parsed_res.value { Some(parse_program) => {