Types converts to typeid implicitly.

This commit is contained in:
Christoffer Lerno
2025-08-22 00:26:18 +02:00
parent d5eec296a0
commit f36e9fea48
8 changed files with 36 additions and 21 deletions

View File

@@ -9,7 +9,7 @@ import std::collections::pair;
@param [in] array
@param [in] element
@require @typekind(array) == SLICE || @typekind(array) == ARRAY
@require @typeis(array[0], $typeof(element)) : "array and element must have the same type"
@require @typematch(array[0], element) : "array and element must have the same type"
*>
macro bool contains(array, element)
{
@@ -26,6 +26,8 @@ macro bool contains(array, element)
@param [in] array
@param [in] element
@require @typekind(array) == SLICE || @typekind(array) == ARRAY
@require @typematch(array[0], element) : "array and element must have the same type"
@return "the first index of the element"
@return? NOT_FOUND
*>
@@ -87,7 +89,7 @@ macro rindex_of(array, element)
@param [&inout] allocator : "The allocator to use, default is the heap allocator"
@require @typekind(arr1) == SLICE || @typekind(arr1) == ARRAY
@require @typekind(arr2) == SLICE || @typekind(arr2) == ARRAY
@require @typeis(arr1[0], $typeof(arr2[0])) : "Arrays must have the same type"
@require @typematch(arr1[0], arr2[0]) : "Arrays must have the same type"
@ensure result.len == arr1.len + arr2.len
*>
macro concat(Allocator allocator, arr1, arr2) @nodiscard
@@ -113,7 +115,7 @@ macro concat(Allocator allocator, arr1, arr2) @nodiscard
@param [in] arr2
@require @typekind(arr1) == SLICE || @typekind(arr1) == ARRAY
@require @typekind(arr2) == SLICE || @typekind(arr2) == ARRAY
@require @typeis(arr1[0], $typeof(arr2[0])) : "Arrays must have the same type"
@require @typematch(arr1[0], arr2[0]) : "Arrays must have the same type"
@ensure return.len == arr1.len + arr2.len
*>
macro tconcat(arr1, arr2) @nodiscard => concat(tmem, arr1, arr2);

View File

@@ -2,10 +2,11 @@ module std::core::values;
import std::core::types;
macro bool @typematch(#value1, #value2) @builtin @const => $typeof(#value1) == $typeof(#value2);
<*
Return true if two values have the same type before any conversions.
*>
macro bool @is_same_type(#value1, #value2) @const => $typeof(#value1).typeid == $typeof(#value2).typeid;
macro bool @is_same_type(#value1, #value2) @const @deprecated("Use @typematch") => $typeof(#value1).typeid == $typeof(#value2).typeid;
macro bool @is_bool(#value) @const => types::is_bool($typeof(#value));
macro bool @is_int(#value) @const => types::is_int($typeof(#value));
macro bool @is_flat_intlike(#value) @const => types::is_flat_intlike($typeof(#value));

View File

@@ -50,7 +50,7 @@ faultdef
"\r" will be filtered from the String.
@param stream : `The stream to read from.`
@require !($defined(&stream) &&& @is_instream(&stream)) : "The value for 'stream' should have been passed as a pointer and not as a value, please add '&'."
@require @is_not_instream_if_ptr(stream) : "The value for 'stream' should have been passed as a pointer and not as a value, please add '&'."
@require @is_instream(stream) : `Make sure that the stream is actually an InStream.`
@param [inout] allocator : `the allocator to use.`
@return `The string containing the data read.`
@@ -76,7 +76,7 @@ macro String? readline(Allocator allocator, stream = io::stdin())
on the temporary allocator and does not need to be freed.
@param stream : `The stream to read from.`
@require !($defined(&stream) &&& @is_instream(&stream)) : "The value for 'stream' should have been passed as a pointer and not as a value, please add '&'."
@require @is_not_instream_if_ptr(stream) : "The value for 'stream' should have been passed as a pointer and not as a value, please add '&'."
@require @is_instream(stream) : `The stream must implement InStream.`
@return `The temporary string containing the data read.`
*>
@@ -90,8 +90,8 @@ macro String? treadline(stream = io::stdin())
@param out_stream : `The stream to write to`
@param in_stream : `The stream to read from.`
@require !($defined(&in_stream) &&& @is_instream(&in_stream)) : "The value for 'in_stream' should have been passed as a pointer and not as a value, please add '&'."
@require !($defined(&out_stream) &&& @is_outstream(&out_stream)) : "The value for 'out_stream' should have been passed as a pointer and not as a value, please add '&'."
@require @is_not_instream_if_ptr(in_stream) : "The value for 'in_stream' should have been passed as a pointer and not as a value, please add '&'."
@require @is_not_outstream_if_ptr(out_stream) : "The value for 'out_stream' should have been passed as a pointer and not as a value, please add '&'."
@require @is_instream(in_stream) : `The in_stream must implement InStream.`
@require @is_outstream(out_stream) : `The out_stream must implement OutStream.`
@return `The number of bytes written`

View File

@@ -37,16 +37,26 @@ fn usz? available(InStream s)
return 0;
}
macro bool @is_instream(#expr)
macro bool @is_instream(#expr) @const
{
return @assignable_to(#expr, InStream);
}
macro bool @is_outstream(#expr)
macro bool @is_not_instream_if_ptr(#expr) @const
{
return !$defined(&#expr) ||| !@is_instream(&#expr);
}
macro bool @is_outstream(#expr) @const
{
return @assignable_to(#expr, OutStream);
}
macro bool @is_not_outstream_if_ptr(#expr) @const
{
return !$defined(&#expr) ||| !@is_outstream(&#expr);
}
<*
@param [&out] ref
@require @is_instream(stream) : "Expected a stream"

View File

@@ -129,7 +129,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 @typematch(sinp, cosp) : "Expected sinp and 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)
@@ -368,7 +368,7 @@ macro log10(x) => $$log10(values::promote_int(x));
<*
@require types::is_numerical($typeof(x)) : `The input must be a floating point value or float vector`
@require types::is_same($typeof(x), $typeof(y)) : `The input types must be equal`
@require @typematch(x, y) : `The input types must be equal`
*>
macro max(x, y, ...)
{
@@ -595,7 +595,7 @@ macro normalize(x) @private
@param then_value : "The vector to get elements from where the mask is 'true'"
@param else_value : "The vector to get elements from where the mask is 'false'"
@require values::@is_vector(then_value) && values::@is_vector(else_value) : "'Then' and 'else' must be vectors."
@require values::@is_same_type(then_value, else_value) : "'Then' and 'else' vectors must be of the same type."
@require @typematch(then_value, else_value) : "'Then' and 'else' vectors must be of the same type."
@require then_value.len == mask.len : "Mask and selected vectors must be of the same width."
@return "a vector of the same type as then/else"
@@ -1135,27 +1135,27 @@ macro overflow_mul_helper(x, y) @local
<*
@param [&out] out : "Where the result of the addition is stored"
@return "Whether the addition resulted in an integer overflow"
@require values::@is_same_type(a, b) : "a and b must be the same type"
@require @typematch(a, b) : "a and b must be the same type"
@require values::@is_flat_intlike(a) &&& values::@is_flat_intlike(b) : "a and b must both be integer or integer vector based"
@require $defined(*out) &&& values::@is_same_type(*out, a) : "out must be a pointer of the same type as a and b"
@require $defined(*out) &&& @typematch(*out, a) : "out must be a pointer of the same type as a and b"
*>
macro bool overflow_add(a, b, out) => $$overflow_add(a, b, out);
<*
@param [&out] out : "Where the result of the subtraction is stored"
@return "Whether the subtraction resulted in an integer overflow"
@require values::@is_same_type(a, b) : "a and b must be the same type"
@require @typematch(a, b) : "a and b must be the same type"
@require values::@is_flat_intlike(a) &&& values::@is_flat_intlike(b) : "a and b must both be integer or integer vector based"
@require $defined(*out) &&& values::@is_same_type(*out, a) : "out must be a pointer of the same type as a and b"
@require $defined(*out) &&& @typematch(*out, a) : "out must be a pointer of the same type as a and b"
*>
macro bool overflow_sub(a, b, out) => $$overflow_sub(a, b, out);
<*
@param [&out] out : "Where the result of the multiplication is stored"
@return "Whether the multiplication resulted in an integer overflow"
@require values::@is_same_type(a, b) : "a and b must be the same type"
@require @typematch(a, b) : "a and b must be the same type"
@require values::@is_flat_intlike(a) &&& values::@is_flat_intlike(b) : "a and b must both be integer or integer vector based"
@require $defined(*out) &&& values::@is_same_type(*out, a) : "out must be a pointer of the same type as a and b"
@require $defined(*out) &&& @typematch(*out, a) : "out must be a pointer of the same type as a and b"
*>
macro bool overflow_mul(a, b, out) => $$overflow_mul(a, b, out);

View File

@@ -19,6 +19,7 @@
- `foo[x][y] = b` now interpreted as `(*&foo[x])[y] = b` which allows overloads to do chained [] accesses.
- Error if a stack allocated variable is too big (configurable with `--max-stack-object-size`).
- Add `@safeinfer` to allow `var` to be used locally.
- Types converts to typeid implicitly.
### Fixes
- List.remove_at would incorrectly trigger ASAN.

View File

@@ -11179,7 +11179,8 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr, bool mutat
if (mutate) sema_expr_flatten_const_ident(expr->access_resolved_expr.parent);
return true;
case EXPR_TYPEINFO:
RETURN_SEMA_ERROR(expr, "A type must be followed by either (...) or '.' unless passed as a macro type argument or assigned to a compile time type variable.");
expr_rewrite_const_typeid(expr, expr->type_expr->type);
return true;
case EXPR_CT_IDENT:
if (mutate && !sema_cast_ct_ident_rvalue(context, expr)) return false;
break;

View File

@@ -2,6 +2,6 @@ module test;
macro @foo($aaa) {}
fn int main(String[] args)
{
@foo(int); // #error: must be followed by either
@foo(int);
return 0;
}