From 4be7ab216ddefec124eaa79c11e45413b7fca294 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 11 Mar 2026 15:51:46 +0300 Subject: [PATCH] math: decimal data type (fixes #21754) --- doc/docs.md | 8 ++++++++ vlib/v/checker/struct.v | 13 +++++-------- .../v/tests/aliases/numeric_alias_empty_init_test.v | 12 ++++++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 vlib/v/tests/aliases/numeric_alias_empty_init_test.v diff --git a/doc/docs.md b/doc/docs.md index 228129ae8..c3ce6308a 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -3624,6 +3624,14 @@ To define a new type `NewType` as an alias for `ExistingType`, do `type NewType = ExistingType`.
This is a special case of a [sum type](#sum-types) declaration. +Numeric aliases can use empty literal syntax for zero/default initialization: + +```v +type Decimal = f64 + +amount := Decimal{} +``` + ### Enums An enum is a group of constant integer values, each having its own name, diff --git a/vlib/v/checker/struct.v b/vlib/v/checker/struct.v index c9ef1bb51..29313411c 100644 --- a/vlib/v/checker/struct.v +++ b/vlib/v/checker/struct.v @@ -614,12 +614,6 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini if type_sym.kind == .interface && type_sym.language != .js { c.error('cannot instantiate interface `${type_sym.name}`', node.pos) } - if type_sym.info is ast.Alias { - if type_sym.info.parent_type.is_number() { - c.error('cannot instantiate number type alias `${type_sym.name}`', node.pos) - return ast.void_type - } - } // allow init structs from generic if they're private except the type is from builtin module if !node.has_update_expr && !type_sym.is_pub && type_sym.kind != .placeholder && type_sym.language != .c && (type_sym.mod != c.mod && !(node.typ.has_flag(.generic) @@ -686,7 +680,7 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini mut info := ast.Struct{} if type_sym.kind == .alias { info_t := type_sym.info as ast.Alias - sym := c.table.sym(info_t.parent_type) + sym := c.table.final_sym(info_t.parent_type) if sym.kind == .placeholder { // pending import symbol did not resolve c.error('unknown struct: ${type_sym.name}', node.pos) return ast.void_type @@ -699,7 +693,10 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini // we do allow []int{}, [10]int{}, map[string]int{} } else { - c.error('alias type name: ${sym.name} is not struct type', node.pos) + if !(sym.is_number() && node.init_fields.len == 0 && !node.has_update_expr) { + c.error('alias type name: ${sym.name} is not struct type', + node.pos) + } } } } else { diff --git a/vlib/v/tests/aliases/numeric_alias_empty_init_test.v b/vlib/v/tests/aliases/numeric_alias_empty_init_test.v new file mode 100644 index 000000000..22bbe929f --- /dev/null +++ b/vlib/v/tests/aliases/numeric_alias_empty_init_test.v @@ -0,0 +1,12 @@ +type Decimal = f64 +type Counter = int + +fn test_empty_init_of_numeric_aliases() { + decimal_zero := Decimal{} + counter_zero := Counter{} + + assert typeof(decimal_zero).name == 'Decimal' + assert typeof(counter_zero).name == 'Counter' + assert decimal_zero == Decimal(0.0) + assert counter_zero == Counter(0) +} -- 2.39.5