From 7cf9c1806f1580bcf028f9579b4a7257f0de5c66 Mon Sep 17 00:00:00 2001 From: Timothy Zakian Date: Tue, 15 Oct 2024 14:57:57 -0700 Subject: [PATCH] Add source locations to `Type` in the Move IR --- .../crates/module-generation/src/generator.rs | 30 +++--- .../src/to_bytecode/translate.rs | 18 ++-- .../move-ir-to-bytecode-syntax/src/syntax.rs | 32 +++--- .../move-ir-to-bytecode/src/compiler.rs | 98 +++++++++++-------- .../move/crates/move-ir-types/src/ast.rs | 60 ++++-------- 5 files changed, 116 insertions(+), 122 deletions(-) diff --git a/external-crates/move/crates/module-generation/src/generator.rs b/external-crates/move/crates/module-generation/src/generator.rs index 8f2dcbef73ddf..ebe0e131993e8 100644 --- a/external-crates/move/crates/module-generation/src/generator.rs +++ b/external-crates/move/crates/module-generation/src/generator.rs @@ -113,13 +113,12 @@ impl<'a> ModuleGenerator<'a> { if !structs.is_empty() { end += 1; }; - - match self.index(end) { - 0 => Type::Address, - 1 => Type::U8, - 2 => Type::U64, - 3 => Type::U128, - 4 => Type::Bool, + let type_ = match self.index(end) { + 0 => Type_::Address, + 1 => Type_::U8, + 2 => Type_::U64, + 3 => Type_::U128, + 4 => Type_::Bool, 5 if !structs.is_empty() => { let index = self.index(structs.len()); let struct_def = structs[index].value.clone(); @@ -133,17 +132,18 @@ impl<'a> ModuleGenerator<'a> { let module_name = ModuleName::module_self(); QualifiedDatatypeIdent::new(module_name, struct_name) }; - Type::Datatype(struct_ident, ty_instants) + Type_::Datatype(struct_ident, ty_instants) } - 6 => Type::U16, - 7 => Type::U32, - 8 => Type::U256, + 6 => Type_::U16, + 7 => Type_::U32, + 8 => Type_::U256, _ => { let index = self.index(ty_param_context.len()); let ty_var = ty_param_context[index].value.clone(); - Type::TypeParameter(ty_var) + Type_::TypeParameter(ty_var) } - } + }; + Spanned::unsafe_no_loc(type_) } fn typ(&mut self, ty_param_context: &[(TypeVar, BTreeSet)]) -> Type { @@ -158,7 +158,7 @@ impl<'a> ModuleGenerator<'a> { // if typ.is_nominal_resource { .... } if self.options.references_allowed && self.gen.gen_bool(0.25) { let is_mutable = self.gen.gen_bool(0.25); - Type::Reference(is_mutable, Box::new(typ)) + Spanned::unsafe_no_loc(Type_::Reference(is_mutable, Box::new(typ))) } else { typ } @@ -209,7 +209,7 @@ impl<'a> ModuleGenerator<'a> { .iter() .map(|(ty_var_, _)| { let param_name = Spanned::unsafe_no_loc(Var_(self.identifier().into())); - let ty = Type::TypeParameter(ty_var_.value.clone()); + let ty = Spanned::unsafe_no_loc(Type_::TypeParameter(ty_var_.value.clone())); (param_name, ty) }) .collect(); diff --git a/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs b/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs index b16e8c6d8fba5..bb1ba8ab8727b 100644 --- a/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs +++ b/external-crates/move/crates/move-compiler/src/to_bytecode/translate.rs @@ -811,11 +811,11 @@ fn base_types(context: &mut Context, bs: Vec) -> Vec { bs.into_iter().map(|b| base_type(context, b)).collect() } -fn base_type(context: &mut Context, sp!(_, bt_): H::BaseType) -> IR::Type { +fn base_type(context: &mut Context, sp!(bt_loc, bt_): H::BaseType) -> IR::Type { use BuiltinTypeName_ as BT; use H::{BaseType_ as B, TypeName_ as TN}; - use IR::Type as IRT; - match bt_ { + use IR::Type_ as IRT; + let type_ = match bt_ { B::Unreachable | B::UnresolvedError => { panic!("ICE should not have reached compilation if there are errors") } @@ -845,15 +845,19 @@ fn base_type(context: &mut Context, sp!(_, bt_): H::BaseType) -> IR::Type { user_specified_name, .. }) => IRT::TypeParameter(type_var(user_specified_name).value), - } + }; + sp(bt_loc, type_) } -fn single_type(context: &mut Context, sp!(_, st_): H::SingleType) -> IR::Type { +fn single_type(context: &mut Context, sp!(st_loc, st_): H::SingleType) -> IR::Type { use H::SingleType_ as S; - use IR::Type as IRT; + use IR::Type_ as IRT; match st_ { S::Base(bt) => base_type(context, bt), - S::Ref(mut_, bt) => IRT::Reference(mut_, Box::new(base_type(context, bt))), + S::Ref(mut_, bt) => sp( + st_loc, + IRT::Reference(mut_, Box::new(base_type(context, bt))), + ), } } diff --git a/external-crates/move/crates/move-ir-to-bytecode-syntax/src/syntax.rs b/external-crates/move/crates/move-ir-to-bytecode-syntax/src/syntax.rs index dd7a22df0f5f4..40a8dcceb7b92 100644 --- a/external-crates/move/crates/move-ir-to-bytecode-syntax/src/syntax.rs +++ b/external-crates/move/crates/move-ir-to-bytecode-syntax/src/syntax.rs @@ -1330,64 +1330,65 @@ fn parse_ability(tokens: &mut Lexer) -> Result<(Ability, Loc), ParseError Result> { + let start_loc = tokens.start_loc(); let t = match tokens.peek() { Tok::NameValue if matches!(tokens.content(), "address") => { tokens.advance()?; - Type::Address + Type_::Address } Tok::NameValue if matches!(tokens.content(), "u8") => { tokens.advance()?; - Type::U8 + Type_::U8 } Tok::NameValue if matches!(tokens.content(), "u16") => { tokens.advance()?; - Type::U16 + Type_::U16 } Tok::NameValue if matches!(tokens.content(), "u32") => { tokens.advance()?; - Type::U32 + Type_::U32 } Tok::NameValue if matches!(tokens.content(), "u64") => { tokens.advance()?; - Type::U64 + Type_::U64 } Tok::NameValue if matches!(tokens.content(), "u128") => { tokens.advance()?; - Type::U128 + Type_::U128 } Tok::NameValue if matches!(tokens.content(), "u256") => { tokens.advance()?; - Type::U256 + Type_::U256 } Tok::NameValue if matches!(tokens.content(), "bool") => { tokens.advance()?; - Type::Bool + Type_::Bool } Tok::NameValue if matches!(tokens.content(), "signer") => { tokens.advance()?; - Type::Signer + Type_::Signer } Tok::NameBeginTyValue if matches!(tokens.content(), "vector<") => { tokens.advance()?; let ty = parse_type(tokens)?; adjust_token(tokens, &[Tok::Greater])?; consume_token(tokens, Tok::Greater)?; - Type::Vector(Box::new(ty)) + Type_::Vector(Box::new(ty)) } Tok::DotNameValue => { let s = parse_qualified_struct_ident(tokens)?; let tys = parse_type_actuals(tokens)?; - Type::Datatype(s, tys) + Type_::Datatype(s, tys) } Tok::Amp => { tokens.advance()?; - Type::Reference(false, Box::new(parse_type(tokens)?)) + Type_::Reference(false, Box::new(parse_type(tokens)?)) } Tok::AmpMut => { tokens.advance()?; - Type::Reference(true, Box::new(parse_type(tokens)?)) + Type_::Reference(true, Box::new(parse_type(tokens)?)) } - Tok::NameValue => Type::TypeParameter(TypeVar_(parse_name(tokens)?)), + Tok::NameValue => Type_::TypeParameter(TypeVar_(parse_name(tokens)?)), t => { return Err(ParseError::InvalidToken { location: current_token_loc(tokens), @@ -1395,7 +1396,8 @@ fn parse_type(tokens: &mut Lexer) -> Result }) } }; - Ok(t) + let end_loc = tokens.previous_end_loc(); + Ok(spanned(tokens.file_hash(), start_loc, end_loc, t)) } // TypeVar: TypeVar = { diff --git a/external-crates/move/crates/move-ir-to-bytecode/src/compiler.rs b/external-crates/move/crates/move-ir-to-bytecode/src/compiler.rs index 020bf1c6523b5..efb218beb89aa 100644 --- a/external-crates/move/crates/move-ir-to-bytecode/src/compiler.rs +++ b/external-crates/move/crates/move-ir-to-bytecode/src/compiler.rs @@ -340,7 +340,7 @@ fn constant_name_as_constant_value_index( ) -> Result { let name_constant = compile_constant( context, - Type::Vector(Box::new(Type::U8)), + &MoveTypeLayout::Vector(Box::new(MoveTypeLayout::U8)), MoveValue::vector_u8(const_name.to_string().into_bytes()), )?; context.constant_index(name_constant) @@ -407,7 +407,11 @@ pub fn compile_module<'a>( constant_name_as_constant_value_index(&mut context, &ir_constant.name)?; } - let constant = compile_constant(&mut context, ir_constant.signature, ir_constant.value)?; + let constant = compile_constant( + &mut context, + &type_to_constant_type_layout(ir_constant.signature)?, + ir_constant.value, + )?; context.declare_constant(ir_constant.name.clone(), constant.clone())?; let const_idx = context.constant_index(constant)?; record_src_loc!(const_decl: context, const_idx, ir_constant.name); @@ -672,22 +676,22 @@ fn compile_type( type_parameters: &HashMap, ty: &Type, ) -> Result { - Ok(match ty { - Type::Address => SignatureToken::Address, - Type::Signer => SignatureToken::Signer, - Type::U8 => SignatureToken::U8, - Type::U16 => SignatureToken::U16, - Type::U32 => SignatureToken::U32, - Type::U64 => SignatureToken::U64, - Type::U128 => SignatureToken::U128, - Type::U256 => SignatureToken::U256, - Type::Bool => SignatureToken::Bool, - Type::Vector(inner_type) => SignatureToken::Vector(Box::new(compile_type( + Ok(match &ty.value { + Type_::Address => SignatureToken::Address, + Type_::Signer => SignatureToken::Signer, + Type_::U8 => SignatureToken::U8, + Type_::U16 => SignatureToken::U16, + Type_::U32 => SignatureToken::U32, + Type_::U64 => SignatureToken::U64, + Type_::U128 => SignatureToken::U128, + Type_::U256 => SignatureToken::U256, + Type_::Bool => SignatureToken::Bool, + Type_::Vector(inner_type) => SignatureToken::Vector(Box::new(compile_type( context, type_parameters, inner_type, )?)), - Type::Reference(is_mutable, inner_type) => { + Type_::Reference(is_mutable, inner_type) => { let inner_token = Box::new(compile_type(context, type_parameters, inner_type)?); if *is_mutable { SignatureToken::MutableReference(inner_token) @@ -695,7 +699,7 @@ fn compile_type( SignatureToken::Reference(inner_token) } } - Type::Datatype(ident, tys) => { + Type_::Datatype(ident, tys) => { let sh_idx = context.datatype_handle_index(ident.clone())?; if tys.is_empty() { @@ -705,7 +709,7 @@ fn compile_type( SignatureToken::DatatypeInstantiation(Box::new((sh_idx, tokens))) } } - Type::TypeParameter(ty_var) => { + Type_::TypeParameter(ty_var) => { let idx = match type_parameters.get(ty_var) { None => bail!("Unbound type parameter {}", ty_var), Some(idx) => *idx, @@ -1267,7 +1271,7 @@ fn compile_expression( Exp_::Value(cv) => match cv.value { CopyableVal_::Address(address) => { let address_value = MoveValue::Address(address); - let constant = compile_constant(context, Type::Address, address_value)?; + let constant = compile_constant(context, &MoveTypeLayout::Address, address_value)?; let idx = context.constant_index(constant)?; push_instr!(exp.loc, Bytecode::LdConst(idx)); function_frame.push()?; @@ -1298,8 +1302,8 @@ fn compile_expression( } CopyableVal_::ByteArray(buf) => { let vec_value = MoveValue::vector_u8(buf); - let ty = Type::Vector(Box::new(Type::U8)); - let constant = compile_constant(context, ty, vec_value)?; + let ty = MoveTypeLayout::Vector(Box::new(MoveTypeLayout::U8)); + let constant = compile_constant(context, &ty, vec_value)?; let idx = context.constant_index(constant)?; push_instr!(exp.loc, Bytecode::LdConst(idx)); function_frame.push()?; @@ -1669,30 +1673,38 @@ fn compile_call( Ok(()) } -fn compile_constant(_context: &mut Context, ty: Type, value: MoveValue) -> Result { - fn type_layout(ty: Type) -> Result { - Ok(match ty { - Type::Address => MoveTypeLayout::Address, - Type::Signer => MoveTypeLayout::Signer, - Type::U8 => MoveTypeLayout::U8, - Type::U16 => MoveTypeLayout::U16, - Type::U32 => MoveTypeLayout::U32, - Type::U64 => MoveTypeLayout::U64, - Type::U128 => MoveTypeLayout::U128, - Type::U256 => MoveTypeLayout::U256, - Type::Bool => MoveTypeLayout::Bool, - Type::Vector(inner_type) => MoveTypeLayout::Vector(Box::new(type_layout(*inner_type)?)), - Type::Reference(_, _) => bail!("References are not supported in constant type layouts"), - Type::TypeParameter(_) => { - bail!("Type parameters are not supported in constant type layouts") - } - Type::Datatype(_ident, _tys) => { - bail!("TODO Structs are not *yet* supported in constant type layouts") - } - }) - } +fn type_to_constant_type_layout(ty: Type) -> Result { + Ok(match ty.value { + Type_::Address => MoveTypeLayout::Address, + Type_::Signer => MoveTypeLayout::Signer, + Type_::U8 => MoveTypeLayout::U8, + Type_::U16 => MoveTypeLayout::U16, + Type_::U32 => MoveTypeLayout::U32, + Type_::U64 => MoveTypeLayout::U64, + Type_::U128 => MoveTypeLayout::U128, + Type_::U256 => MoveTypeLayout::U256, + Type_::Bool => MoveTypeLayout::Bool, + Type_::Vector(inner_type) => { + MoveTypeLayout::Vector(Box::new(type_to_constant_type_layout(*inner_type)?)) + } + Type_::Reference(_, _) => { + bail!("References are not supported in constant type layouts") + } + Type_::TypeParameter(_) => { + bail!("Type parameters are not supported in constant type layouts") + } + Type_::Datatype(_ident, _tys) => { + bail!("TODO Structs are not *yet* supported in constant type layouts") + } + }) +} - Constant::serialize_constant(&type_layout(ty)?, &value) +fn compile_constant( + _context: &mut Context, + layout: &MoveTypeLayout, + value: MoveValue, +) -> Result { + Constant::serialize_constant(layout, &value) .ok_or_else(|| format_err!("Could not serialize constant")) } @@ -1793,7 +1805,7 @@ fn compile_bytecode( IRBytecode_::LdTrue => Bytecode::LdTrue, IRBytecode_::LdFalse => Bytecode::LdFalse, IRBytecode_::LdConst(ty, v) => { - let constant = compile_constant(context, ty, v)?; + let constant = compile_constant(context, &type_to_constant_type_layout(ty)?, v)?; Bytecode::LdConst(context.constant_index(constant)?) } IRBytecode_::LdNamedConst(c) => Bytecode::LdConst(context.named_constant_index(&c)?), diff --git a/external-crates/move/crates/move-ir-types/src/ast.rs b/external-crates/move/crates/move-ir-types/src/ast.rs index e17c328967703..0fcd68c82dee4 100644 --- a/external-crates/move/crates/move-ir-types/src/ast.rs +++ b/external-crates/move/crates/move-ir-types/src/ast.rs @@ -135,9 +135,12 @@ pub enum Ability { // Types //************************************************************************************************** +/// The type of a single value coupled with source location information. +pub type Type = Spanned; + /// The type of a single value #[derive(Debug, PartialEq, Clone)] -pub enum Type { +pub enum Type_ { /// `address` Address, /// `signer` @@ -821,33 +824,6 @@ impl Ability { pub const KEY: &'static str = "key"; } -impl Type { - /// Creates a new struct type - pub fn r#struct(ident: QualifiedDatatypeIdent, type_actuals: Vec) -> Type { - Type::Datatype(ident, type_actuals) - } - - /// Creates a new reference type from its mutability and underlying type - pub fn reference(is_mutable: bool, t: Type) -> Type { - Type::Reference(is_mutable, Box::new(t)) - } - - /// Creates a new address type - pub fn address() -> Type { - Type::Address - } - - /// Creates a new u64 type - pub fn u64() -> Type { - Type::U64 - } - - /// Creates a new bool type - pub fn bool() -> Type { - Type::Bool - } -} - impl QualifiedDatatypeIdent { /// Creates a new StructType handle from the name of the module alias and the name of the struct pub fn new(module: ModuleName, name: DatatypeName) -> Self { @@ -1440,24 +1416,24 @@ fn format_struct_type_formals(formals: &[DatatypeTypeParameter]) -> String { } } -impl fmt::Display for Type { +impl fmt::Display for Type_ { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Type::U8 => write!(f, "u8"), - Type::U16 => write!(f, "u16"), - Type::U32 => write!(f, "u32"), - Type::U64 => write!(f, "u64"), - Type::U128 => write!(f, "u128"), - Type::U256 => write!(f, "u256"), - Type::Bool => write!(f, "bool"), - Type::Address => write!(f, "address"), - Type::Signer => write!(f, "signer"), - Type::Vector(ty) => write!(f, "vector<{}>", ty), - Type::Datatype(ident, tys) => write!(f, "{}{}", ident, format_type_actuals(tys)), - Type::Reference(is_mutable, t) => { + Type_::U8 => write!(f, "u8"), + Type_::U16 => write!(f, "u16"), + Type_::U32 => write!(f, "u32"), + Type_::U64 => write!(f, "u64"), + Type_::U128 => write!(f, "u128"), + Type_::U256 => write!(f, "u256"), + Type_::Bool => write!(f, "bool"), + Type_::Address => write!(f, "address"), + Type_::Signer => write!(f, "signer"), + Type_::Vector(ty) => write!(f, "vector<{}>", ty), + Type_::Datatype(ident, tys) => write!(f, "{}{}", ident, format_type_actuals(tys)), + Type_::Reference(is_mutable, t) => { write!(f, "&{}{}", if *is_mutable { "mut " } else { "" }, t) } - Type::TypeParameter(s) => write!(f, "{}", s), + Type_::TypeParameter(s) => write!(f, "{}", s), } } }