From ec45a2dfe965255de8b04b56ae0f2809976cb552 Mon Sep 17 00:00:00 2001 From: Volodymyr Herashchenko Date: Thu, 19 Mar 2026 16:01:06 +0200 Subject: [PATCH 1/3] fix: remove hardcoded built-ins --- src/parse.rs | 31 +++++++++++-------------------- src/types.rs | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index c42c6f3d..d0afabb9 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -26,7 +26,7 @@ use crate::str::{ AliasName, Binary, Decimal, FunctionName, Hexadecimal, Identifier, JetName, ModuleName, WitnessName, }; -use crate::types::{AliasedType, BuiltinAlias, TypeConstructible}; +use crate::types::{AliasedType, BuiltinAlias, TypeConstructible, UIntType}; /// A program is a sequence of items. #[derive(Clone, Debug)] @@ -1002,26 +1002,17 @@ impl ChumskyParse for AliasedType { I: ValueInput<'tokens, Token = Token<'src>, Span = Span>, { let atom = select! { - Token::Ident(ident) => { - match ident - { - "u1" => AliasedType::u1(), - "u2" => AliasedType::u2(), - "u4" => AliasedType::u4(), - "u8" => AliasedType::u8(), - "u16" => AliasedType::u16(), - "u32" => AliasedType::u32(), - "u64" => AliasedType::u64(), - "u128" => AliasedType::u128(), - "u256" => AliasedType::u256(), - "Ctx8" | "Pubkey" | "Message64" | "Message" | "Signature" | "Scalar" | "Fe" | "Gej" - | "Ge" | "Point" | "Height" | "Time" | "Distance" | "Duration" | "Lock" | "Outpoint" - | "Confidential1" | "ExplicitAsset" | "Asset1" | "ExplicitAmount" | "Amount1" - | "ExplicitNonce" | "Nonce" | "TokenAmount1" => AliasedType::builtin(BuiltinAlias::from_str(ident).unwrap()), - "bool" => AliasedType::boolean(), - _ => AliasedType::alias(AliasName::from_str_unchecked(ident)), + Token::Ident(ident) => { + if ident == "bool" { + AliasedType::boolean() + } else if let Ok(uint_type) = UIntType::from_str(ident) { + AliasedType::from(uint_type) + } else if let Ok(builtin) = BuiltinAlias::from_str(ident) { + AliasedType::builtin(builtin) + } else { + AliasedType::alias(AliasName::from_str_unchecked(ident)) + } } - }, }; let num = select! { diff --git a/src/types.rs b/src/types.rs index e68c9f06..2a4c8784 100644 --- a/src/types.rs +++ b/src/types.rs @@ -193,6 +193,25 @@ impl fmt::Display for UIntType { } } +impl FromStr for UIntType { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "u1" => Ok(UIntType::U1), + "u2" => Ok(UIntType::U2), + "u4" => Ok(UIntType::U4), + "u8" => Ok(UIntType::U8), + "u16" => Ok(UIntType::U16), + "u32" => Ok(UIntType::U32), + "u64" => Ok(UIntType::U64), + "u128" => Ok(UIntType::U128), + "u256" => Ok(UIntType::U256), + _ => Err("Unknown integer type".to_string()), + } + } +} + impl TryFrom<&StructuralType> for UIntType { type Error = (); From 0f54d67e1a683e8e4b2f97e080b18ae16f682111 Mon Sep 17 00:00:00 2001 From: Volodymyr Herashchenko Date: Thu, 19 Mar 2026 16:05:26 +0200 Subject: [PATCH 2/3] feat: add check for redefining built-in types That includes `bool` type, all unsigned integer types and built-in aliases. --- src/error.rs | 5 +++++ src/parse.rs | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/error.rs b/src/error.rs index 1ded6fdd..2671cf2c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -429,6 +429,7 @@ pub enum Error { IntegerOutOfBounds(UIntType), UndefinedVariable(Identifier), RedefinedAlias(AliasName), + RedefinedAliasAsBuiltin(AliasName), UndefinedAlias(AliasName), VariableReuseInPattern(Identifier), WitnessReused(WitnessName), @@ -551,6 +552,10 @@ impl fmt::Display for Error { f, "Type alias `{identifier}` was defined multiple times" ), + Error::RedefinedAliasAsBuiltin(identifier) => write!( + f, + "Type alias `{identifier}` is already exists as built-in alias" + ), Error::UndefinedAlias(identifier) => write!( f, "Type alias `{identifier}` is not defined" diff --git a/src/parse.rs b/src/parse.rs index d0afabb9..bb7cf653 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1452,7 +1452,25 @@ impl ChumskyParse for TypeAlias { where I: ValueInput<'tokens, Token = Token<'src>, Span = Span>, { - let name = AliasName::parser().map_with(|name, e| (name, e.span())); + let name = AliasName::parser() + .validate(|name, e, emit| { + let ident = name.as_inner(); + let known_type = if ident == "bool" { + Some(AliasedType::boolean()) + } else if let Ok(uint_type) = UIntType::from_str(ident) { + Some(AliasedType::from(uint_type)) + } else if let Ok(builtin) = BuiltinAlias::from_str(ident) { + Some(AliasedType::builtin(builtin)) + } else { + None + }; + + if known_type.is_some() { + emit.emit(Error::RedefinedAliasAsBuiltin(name.clone()).with_span(e.span())); + } + name + }) + .map_with(|name, e| (name, e.span())); just(Token::Type) .ignore_then(name) @@ -2154,3 +2172,19 @@ impl crate::ArbitraryRec for Match { }) } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_reject_redefined_builtin_type() { + let ty = TypeAlias::parse_from_str("type Ctx8 = u32") + .expect_err("Redifining built-in alias should be rejected"); + + assert_eq!( + ty.error(), + &Error::RedefinedAliasAsBuiltin(AliasName::from_str_unchecked("Ctx8")) + ); + } +} From 887c6816c346b40368d8a941e57a5d0818ecd806 Mon Sep 17 00:00:00 2001 From: Volodymyr Herashchenko Date: Thu, 19 Mar 2026 16:09:21 +0200 Subject: [PATCH 3/3] fix: add whitespace after comma in `Either` display --- src/types.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/types.rs b/src/types.rs index 2a4c8784..ae778a4f 100644 --- a/src/types.rs +++ b/src/types.rs @@ -37,7 +37,7 @@ impl TypeInner { match self { TypeInner::Either(_, _) => match n_children_yielded { 0 => f.write_str("Either<"), - 1 => f.write_str(","), + 1 => f.write_str(", "), n => { debug_assert_eq!(n, 2); f.write_str(">") @@ -1113,5 +1113,7 @@ mod tests { assert_eq!("[(); 3]", &array.to_string()); let list = ResolvedType::list(ResolvedType::unit(), NonZeroPow2Usize::TWO); assert_eq!("List<(), 2>", &list.to_string()); + let either = ResolvedType::either(ResolvedType::unit(), ResolvedType::u32()); + assert_eq!("Either<(), u32>", &either.to_string()); } }