diff --git a/lib/std/collections/hashmap.c3 b/lib/std/collections/hashmap.c3 index bb8b05779..bc02eb046 100644 --- a/lib/std/collections/hashmap.c3 +++ b/lib/std/collections/hashmap.c3 @@ -195,7 +195,7 @@ fn Entry*? HashMap.get_entry(&map, Key key) <* Get the value or update and - @require $assignable(#expr, Value) + @require @assignable_to(#expr, Value) *> macro Value HashMap.@get_or_set(&map, Key key, Value #expr) { diff --git a/lib/std/collections/object.c3 b/lib/std/collections/object.c3 index 5f42e561d..1deac0b95 100644 --- a/lib/std/collections/object.c3 +++ b/lib/std/collections/object.c3 @@ -203,7 +203,7 @@ macro Object* Object.object_from_value(&self, value) @private return value; $case $Type.typeid == void*.typeid: return &NULL_OBJECT; - $case $assignable(value, String): + $case @assignable_to(value, String): return new_string(value, self.allocator); $default: $error "Unsupported object type."; diff --git a/lib/std/collections/tuple.c3 b/lib/std/collections/tuple.c3 index 07dece104..15764f420 100644 --- a/lib/std/collections/tuple.c3 +++ b/lib/std/collections/tuple.c3 @@ -9,8 +9,8 @@ struct Pair <* @param [&out] a @param [&out] b - @require $assignable(self.first, $typeof(*a)) : "You cannot assign the first value to a" - @require $assignable(self.second, $typeof(*b)) : "You cannot assign the second value to b" + @require @assignable_to(self.first, $typeof(*a)) : "You cannot assign the first value to a" + @require @assignable_to(self.second, $typeof(*b)) : "You cannot assign the second value to b" *> macro void Pair.unpack(&self, a, b) { @@ -31,9 +31,9 @@ struct Triple @param [&out] a @param [&out] b @param [&out] c - @require $assignable(self.first, $typeof(*a)) : "You cannot assign the first value to a" - @require $assignable(self.second, $typeof(*b)) : "You cannot assign the second value to b" - @require $assignable(self.third, $typeof(*c)) : "You cannot assign the second value to c" + @require @assignable_to(self.first, $typeof(*a)) : "You cannot assign the first value to a" + @require @assignable_to(self.second, $typeof(*b)) : "You cannot assign the second value to b" + @require @assignable_to(self.third, $typeof(*c)) : "You cannot assign the second value to c" *> macro void Triple.unpack(&self, a, b, c) { diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index 15ebf833b..9da8aea7c 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -107,6 +107,22 @@ macro @addr(#val) @builtin $endif } +macro typeid @typeid(#value) @const @builtin +{ + return $typeof(#value).typeid; +} + +macro TypeKind @typekind(#value) @const @builtin +{ + return $typeof(#value).kindof; +} + +macro bool @typeis(#value, $Type) @const @builtin +{ + return $typeof(#value).typeid == $Type.typeid; +} + + fn bool print_backtrace(String message, int backtraces_to_ignore) @if (env::NATIVE_STACKTRACE) => @stack_mem(0x1100; Allocator smem) { void*[256] buffer; @@ -291,7 +307,7 @@ macro enum_by_name($Type, String enum_name) @builtin @param $Type : `The type of the enum` @require $Type.kindof == ENUM : `Only enums may be used` @require $defined($Type.#value) : `Expected '#value' to match an enum associated value` - @require $assignable(value, $typeof(($Type){}.#value)) : `Expected the value to match the type of the associated value` + @require @assignable_to(value, $typeof(($Type){}.#value)) : `Expected the value to match the type of the associated value` @ensure @typeis(return, $Type) @return? NOT_FOUND *> @@ -344,7 +360,7 @@ macro bool @unlikely(bool #value, $probability = 1.0) @builtin <* @require values::@is_int(#value) || values::@is_bool(#value) - @require $assignable(expected, $typeof(#value)) + @require @assignable_to(expected, $typeof(#value)) @require $probability >= 0 && $probability <= 1.0 *> macro @expect(#value, expected, $probability = 1.0) @builtin diff --git a/lib/std/core/mem.c3 b/lib/std/core/mem.c3 index 826aa631e..4641442d6 100644 --- a/lib/std/core/mem.c3 +++ b/lib/std/core/mem.c3 @@ -44,7 +44,7 @@ fn usz os_pagesize() @param ptr : "The pointer address to load from." @param mask : "The mask for the load" @param passthru : "The value to use for non masked values" - @require $assignable(&&passthru, $typeof(ptr)) : "Pointer and passthru must match" + @require @assignable_to(&&passthru, $typeof(ptr)) : "Pointer and passthru must match" @require @typekind(passthru) == VECTOR : "Expected passthru to be a vector" @require passthru.len == mask.len : "Mask and passthru must have the same length" @@ -63,7 +63,7 @@ macro masked_load(ptr, bool[<*>] mask, passthru) @param passthru : "The value to use for non masked values" @param $alignment : "The alignment to assume for the pointer" - @require $assignable(&&passthru, $typeof(ptr)) : "Pointer and passthru must match" + @require @assignable_to(&&passthru, $typeof(ptr)) : "Pointer and passthru must match" @require @typekind(passthru) == VECTOR : "Expected passthru to be a vector" @require passthru.len == mask.len : "Mask and passthru must have the same length" @require @constant_is_power_of_2($alignment) : "The alignment must be a power of two" @@ -84,7 +84,7 @@ macro @masked_load_aligned(ptr, bool[<*>] mask, passthru, usz $alignment) @require @typekind(ptrvec) == VECTOR : "Expected ptrvec to be a vector" @require @typekind(passthru) == VECTOR : "Expected passthru to be a vector" - @require $assignable(&&passthru[0], $typeof(ptrvec[0])) : "Pointer and passthru must match" + @require @assignable_to(&&passthru[0], $typeof(ptrvec[0])) : "Pointer and passthru must match" @require passthru.len == mask.len : "Mask and passthru must have the same length" @require mask.len == ptrvec.len : "Mask and ptrvec must have the same length" @@ -106,7 +106,7 @@ macro gather(ptrvec, bool[<*>] mask, passthru) @require @typekind(ptrvec) == VECTOR : "Expected ptrvec to be a vector" @require @typekind(passthru) == VECTOR : "Expected passthru to be a vector" - @require $assignable(&&passthru[0], $typeof(ptrvec[0])) : "Pointer and passthru must match" + @require @assignable_to(&&passthru[0], $typeof(ptrvec[0])) : "Pointer and passthru must match" @require passthru.len == mask.len : "Mask and passthru must have the same length" @require mask.len == ptrvec.len : "Mask and ptrvec must have the same length" @require @constant_is_power_of_2($alignment) : "The alignment must be a power of two" @@ -126,7 +126,7 @@ macro @gather_aligned(ptrvec, bool[<*>] mask, passthru, usz $alignment) @param value : "The value to store masked" @param mask : "The mask for the store" - @require $assignable(&&value, $typeof(ptr)) : "Pointer and value must match" + @require @assignable_to(&&value, $typeof(ptr)) : "Pointer and value must match" @require @typekind(value) == VECTOR : "Expected value to be a vector" @require value.len == mask.len : "Mask and value must have the same length" *> @@ -141,7 +141,7 @@ macro masked_store(ptr, value, bool[<*>] mask) @param mask : "The mask for the store" @param $alignment : "The alignment of the pointer" - @require $assignable(&&value, $typeof(ptr)) : "Pointer and value must match" + @require @assignable_to(&&value, $typeof(ptr)) : "Pointer and value must match" @require @typekind(value) == VECTOR : "Expected value to be a vector" @require value.len == mask.len : "Mask and value must have the same length" @require @constant_is_power_of_2($alignment) : "The alignment must be a power of two" @@ -158,7 +158,7 @@ macro @masked_store_aligned(ptr, value, bool[<*>] mask, usz $alignment) @param mask : "The mask for the store" @require @typekind(ptrvec) == VECTOR : "Expected ptrvec to be a vector" @require @typekind(value) == VECTOR : "Expected value to be a vector" - @require $assignable(&&value[0], $typeof(ptrvec[0])) : "Pointer and value must match" + @require @assignable_to(&&value[0], $typeof(ptrvec[0])) : "Pointer and value must match" @require value.len == mask.len : "Mask and value must have the same length" @require mask.len == ptrvec.len : "Mask and ptrvec must have the same length" @@ -176,7 +176,7 @@ macro scatter(ptrvec, value, bool[<*>] mask) @require @typekind(ptrvec) == VECTOR : "Expected ptrvec to be a vector" @require @typekind(value) == VECTOR : "Expected value to be a vector" - @require $assignable(&&value[0], $typeof(ptrvec[0])) : "Pointer and value must match" + @require @assignable_to(&&value[0], $typeof(ptrvec[0])) : "Pointer and value must match" @require value.len == mask.len : "Mask and value must have the same length" @require mask.len == ptrvec.len : "Mask and ptrvec must have the same length" @require @constant_is_power_of_2($alignment) : "The alignment must be a power of two" @@ -728,7 +728,7 @@ fn void* tmalloc(usz size, usz alignment = 0) @builtin @inline @nodiscard <* @require $vacount < 2 : "Too many arguments." - @require $vacount == 0 ||| $assignable($vaexpr[0], $Type) : "The second argument must be an initializer for the type" + @require $vacount == 0 ||| @assignable_to($vaexpr[0], $Type) : "The second argument must be an initializer for the type" @require $Type.alignof <= DEFAULT_MEM_ALIGNMENT : "Types with alignment exceeding the default must use 'alloc_aligned' instead" *> macro new($Type, ...) @nodiscard @@ -744,7 +744,7 @@ macro new($Type, ...) @nodiscard <* @require $vacount < 2 : "Too many arguments." - @require $vacount == 0 ||| $assignable($vaexpr[0], $Type) : "The second argument must be an initializer for the type" + @require $vacount == 0 ||| @assignable_to($vaexpr[0], $Type) : "The second argument must be an initializer for the type" @require $Type.alignof <= DEFAULT_MEM_ALIGNMENT : "Types with alignment exceeding the default must use 'alloc_aligned' instead" *> macro new_with_padding($Type, usz padding, ...) @nodiscard @@ -762,7 +762,7 @@ macro new_with_padding($Type, usz padding, ...) @nodiscard Allocate using an aligned allocation. This is necessary for types with a default memory alignment exceeding DEFAULT_MEM_ALIGNMENT. IMPORTANT! It must be freed using free_aligned. @require $vacount < 2 : "Too many arguments." - @require $vacount == 0 ||| $assignable($vaexpr[0], $Type) : "The second argument must be an initializer for the type" + @require $vacount == 0 ||| @assignable_to($vaexpr[0], $Type) : "The second argument must be an initializer for the type" *> macro new_aligned($Type, ...) @nodiscard { @@ -802,7 +802,7 @@ macro alloc_aligned($Type) @nodiscard <* @require $vacount < 2 : "Too many arguments." - @require $vacount == 0 ||| $assignable($vaexpr[0], $Type) : "The second argument must be an initializer for the type" + @require $vacount == 0 ||| @assignable_to($vaexpr[0], $Type) : "The second argument must be an initializer for the type" *> macro tnew($Type, ...) @nodiscard { @@ -817,7 +817,7 @@ macro tnew($Type, ...) @nodiscard <* @require $vacount < 2 : "Too many arguments." - @require $vacount == 0 ||| $assignable($vaexpr[0], $Type) : "The second argument must be an initializer for the type" + @require $vacount == 0 ||| @assignable_to($vaexpr[0], $Type) : "The second argument must be an initializer for the type" *> macro temp_with_padding($Type, usz padding, ...) @nodiscard { diff --git a/lib/std/core/mem_allocator.c3 b/lib/std/core/mem_allocator.c3 index dae3e89bd..699777ee3 100644 --- a/lib/std/core/mem_allocator.c3 +++ b/lib/std/core/mem_allocator.c3 @@ -167,7 +167,7 @@ macro void free_aligned(Allocator allocator, void* ptr) <* @require $Type.alignof <= mem::DEFAULT_MEM_ALIGNMENT : "Types with alignment exceeding the default must use 'new_aligned' instead" @require $vacount < 2 : "Too many arguments." - @require $vacount == 0 ||| $assignable($vaexpr[0], $Type) : "The second argument must be an initializer for the type" + @require $vacount == 0 ||| @assignable_to($vaexpr[0], $Type) : "The second argument must be an initializer for the type" *> macro new(Allocator allocator, $Type, ...) @nodiscard { @@ -183,7 +183,7 @@ macro new(Allocator allocator, $Type, ...) @nodiscard <* @require $Type.alignof <= mem::DEFAULT_MEM_ALIGNMENT : "Types with alignment exceeding the default must use 'new_aligned' instead" @require $vacount < 2 : "Too many arguments." - @require $vacount == 0 ||| $assignable($vaexpr[0], $Type) : "The second argument must be an initializer for the type" + @require $vacount == 0 ||| @assignable_to($vaexpr[0], $Type) : "The second argument must be an initializer for the type" *> macro new_try(Allocator allocator, $Type, ...) @nodiscard { @@ -200,7 +200,7 @@ macro new_try(Allocator allocator, $Type, ...) @nodiscard Allocate using an aligned allocation. This is necessary for types with a default memory alignment exceeding DEFAULT_MEM_ALIGNMENT. IMPORTANT! It must be freed using free_aligned. @require $vacount < 2 : "Too many arguments." - @require $vacount == 0 ||| $assignable($vaexpr[0], $Type) : "The second argument must be an initializer for the type" + @require $vacount == 0 ||| @assignable_to($vaexpr[0], $Type) : "The second argument must be an initializer for the type" *> macro new_aligned(Allocator allocator, $Type, ...) @nodiscard { @@ -464,7 +464,7 @@ macro usz temp_allocator_default_reserve_size() @local $endswitch } -macro Allocator heap() => thread_allocator; +macro Allocator heap() @deprecated("Use 'mem' instead.") => thread_allocator; <* @require !top_temp : "This should never be called when temp already exists" @@ -487,7 +487,7 @@ fn Allocator create_temp_allocator(Allocator allocator, usz size, usz reserve, u return current_temp = top_temp = allocator::new_temp_allocator(allocator, size, reserve, min_size, realloc_size)!!; } -macro Allocator temp() +macro Allocator temp() @deprecated("Use 'tmem' instead") { return current_temp; } diff --git a/lib/std/core/values.c3 b/lib/std/core/values.c3 index fb020afe3..7ecdde928 100644 --- a/lib/std/core/values.c3 +++ b/lib/std/core/values.c3 @@ -2,9 +2,6 @@ module std::core::values; import std::core::types; -macro typeid @typeid(#value) @const @builtin => $typeof(#value).typeid; -macro TypeKind @typekind(#value) @const @builtin => $typeof(#value).kindof; -macro bool @typeis(#value, $Type) @const @builtin => $typeof(#value).typeid == $Type.typeid; <* Return true if two values have the same type before any conversions. *> @@ -18,7 +15,7 @@ macro bool @is_promotable_to_floatlike(#value) @const => types::is_promotable_to macro bool @is_promotable_to_float(#value) @const => types::is_promotable_to_float($typeof(#value)); macro bool @is_vector(#value) @const => types::is_vector($typeof(#value)); macro bool @is_same_vector_type(#value1, #value2) @const => types::is_same_vector_type($typeof(#value1), $typeof(#value2)); -macro bool @assign_to(#value1, #value2) @const => $assignable(#value1, $typeof(#value2)); +macro bool @assign_to(#value1, #value2) @const => @assignable_to(#value1, $typeof(#value2)); macro bool @is_lvalue(#value) => $defined(#value = #value); macro bool @is_const(#foo) @const @builtin { diff --git a/lib/std/io/io.c3 b/lib/std/io/io.c3 index 77fbac8e4..57c340388 100644 --- a/lib/std/io/io.c3 +++ b/lib/std/io/io.c3 @@ -120,7 +120,7 @@ macro usz? fprint(out, x) $case ZString: return out.write(x.str_view()); $case DString: return out.write(x.str_view()); $default: - $if $assignable(x, String): + $if @assignable_to(x, String): return out.write((String)x); $else $if is_struct_with_default_print($Type): diff --git a/lib/std/io/stream.c3 b/lib/std/io/stream.c3 index 39e73d067..48e63b7e0 100644 --- a/lib/std/io/stream.c3 +++ b/lib/std/io/stream.c3 @@ -39,12 +39,12 @@ fn usz? available(InStream s) macro bool @is_instream(#expr) { - return $assignable(#expr, InStream); + return @assignable_to(#expr, InStream); } macro bool @is_outstream(#expr) { - return $assignable(#expr, OutStream); + return @assignable_to(#expr, OutStream); } <* diff --git a/lib/std/math/math.c3 b/lib/std/math/math.c3 index d46e336f4..4553f03d6 100644 --- a/lib/std/math/math.c3 +++ b/lib/std/math/math.c3 @@ -131,7 +131,7 @@ macro atan2(x, y) @require values::@is_int(x) || values::@is_float(x) : "Expected an integer or floating point value" @require @typekind(sinp) == POINTER : "Expected sinp to be a pointer" @require values::@is_same_type(sinp, cosp) : "Expected sinp and cosp to have the same type" - @require $assignable(x, $typeof(*sinp)) : "Expected x and sinp/cosp to have the same type" + @require @assignable_to(x, $typeof(*sinp)) : "Expected x and sinp/cosp to have the same type" *> macro sincos_ref(x, sinp, cosp) { @@ -397,7 +397,7 @@ macro nearbyint(x) => $$nearbyint(x); <* @require values::@is_promotable_to_floatlike(x) : `The input must be a number or a float vector` - @require $assignable(exp, $typeof(values::promote_int(x))) || values::@is_int(exp) : `The input must be an integer, castable to the type of x` + @require @assignable_to(exp, $typeof(values::promote_int(x))) || values::@is_int(exp) : `The input must be an integer, castable to the type of x` *> macro pow(x, exp) { diff --git a/lib/std/math/random.c3 b/lib/std/math/random.c3 index e3bbf4034..fb1cf4114 100644 --- a/lib/std/math/random.c3 +++ b/lib/std/math/random.c3 @@ -133,7 +133,7 @@ macro double next_double(random) } // True if the value is a Random. -macro bool is_random(random) => $assignable(random, Random); +macro bool is_random(random) => @assignable_to(random, Random); macro uint128 @long_to_int128(#function) => (uint128)#function << 64 + #function; macro ulong @int_to_long(#function) => (ulong)#function << 32 + #function; diff --git a/lib/std/sort/countingsort.c3 b/lib/std/sort/countingsort.c3 index 6d2559937..633e597f1 100644 --- a/lib/std/sort/countingsort.c3 +++ b/lib/std/sort/countingsort.c3 @@ -32,7 +32,7 @@ alias Indexs @private = char[256]; alias ElementType = $typeof((Type){}[0]); const bool NO_KEY_FN @private = types::is_same(KeyFn, EmptySlot); -const bool KEY_BY_VALUE @private = NO_KEY_FN ||| $assignable((Type){}[0], KeyFn.paramsof[0].type); +const bool KEY_BY_VALUE @private = NO_KEY_FN ||| @assignable_to((ElementType){}, KeyFn.paramsof[0].type); const bool LIST_HAS_REF @private = $defined(&(Type){}[0]); alias KeyFnReturnType @if(!NO_KEY_FN) = $typefrom(KeyFn.returns) ; diff --git a/lib/std/sort/insertionsort.c3 b/lib/std/sort/insertionsort.c3 index 29107ec9b..4be2893af 100644 --- a/lib/std/sort/insertionsort.c3 +++ b/lib/std/sort/insertionsort.c3 @@ -25,7 +25,7 @@ fn void isort(Type list, usz low, usz high, CmpFn comp, Context context) { var $has_cmp = @is_valid_macro_slot(comp); var $has_context = @is_valid_macro_slot(context); - var $cmp_by_value = $has_cmp &&& $assignable(list[0], CmpFn.paramsof[0].type); + var $cmp_by_value = $has_cmp &&& @assignable_to(list[0], CmpFn.paramsof[0].type); var $has_get_ref = $defined(&list[0]); for (usz i = low; i < high; ++i) { diff --git a/lib/std/sort/quicksort.c3 b/lib/std/sort/quicksort.c3 index 34c5d4b29..c1d73b1fc 100644 --- a/lib/std/sort/quicksort.c3 +++ b/lib/std/sort/quicksort.c3 @@ -115,7 +115,7 @@ macro @partition(Type list, isz l, isz h, CmpFn cmp, Context context) { var $has_cmp = @is_valid_macro_slot(cmp); var $has_context = @is_valid_macro_slot(context); - var $cmp_by_value = $has_cmp &&& $assignable(list[0], CmpFn.paramsof[0].type); + var $cmp_by_value = $has_cmp &&& @assignable_to(list[0], CmpFn.paramsof[0].type); ElementType pivot = list[l]; while (l < h) diff --git a/lib/std/sort/sorted.c3 b/lib/std/sort/sorted.c3 index d57c2c971..bf4fea6f0 100644 --- a/lib/std/sort/sorted.c3 +++ b/lib/std/sort/sorted.c3 @@ -39,7 +39,7 @@ macro int @sort_cmp(list, pos, cmp, ctx) @local { var $has_cmp = @is_valid_macro_slot(cmp); var $has_context = @is_valid_macro_slot(ctx); - var $cmp_by_value = $has_cmp &&& $assignable(list[0], $typeof(cmp).paramsof[0].type); + var $cmp_by_value = $has_cmp &&& @assignable_to(list[0], $typeof(cmp).paramsof[0].type); var a = list[pos]; var b = list[pos+1]; diff --git a/releasenotes.md b/releasenotes.md index 1f01be5ca..6ce94f5b4 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -27,6 +27,8 @@ - Add "@structlike" for typedefs. - "poison" the current function early when a declaration can't be correctly resolved. - Add komihash, a5hash, metrohash64, metrohash128, and wyhash2 variants with tests/benchmark. #2293 +- '$assignable' is deprecated. +- Deprecate allocator::heap() and allocator::temp() ### Fixes - mkdir/rmdir would not work properly with substring paths on non-windows platforms. diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index f187ad390..f2258fa96 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -10556,6 +10556,7 @@ static inline bool sema_expr_analyse_iota_decl(SemaContext *context, Expr *expr) static inline bool sema_expr_analyse_assignable(SemaContext *context, Expr *expr) { + SEMA_DEPRECATED(expr, "$assignable is deprecated, use the '@assignable_to' macro instead."); ASSERT_SPAN(expr, expr->resolve_status == RESOLVE_RUNNING); Expr *type_expr = exprptr(expr->assignable_expr.type); bool in_no_eval = context->call_env.in_no_eval;