- Change typedef and const enums to not convert from literals by default. (#2934)

- Add `@constinit` to allow old typedef behaviour.
This commit is contained in:
Christoffer Lerno
2026-02-13 20:39:47 +01:00
committed by GitHub
parent bbf89815d6
commit e299a4b630
12 changed files with 37 additions and 19 deletions

View File

@@ -5,8 +5,8 @@ module std::hash::fnv32a;
typedef Fnv32a = uint;
const FNV32A_START @private = 0x811c9dc5;
const FNV32A_MUL @private = 0x01000193;
const FNV32A_START @private = (Fnv32a)0x811c9dc5;
const FNV32A_MUL @private = (Fnv32a)0x01000193;
macro void update(h, char x) @private => *h = (*h ^ ($typeof(*h))x) * FNV32A_MUL;
@@ -32,10 +32,10 @@ macro void Fnv32a.update_char(&self, char c)
fn uint hash(char[] data)
{
uint h = FNV32A_START;
Fnv32a h = FNV32A_START;
foreach (char x : data)
{
update(&h, x);
}
return h;
return (uint)h;
}

View File

@@ -5,10 +5,10 @@ module std::hash::fnv64a;
typedef Fnv64a = ulong;
const FNV64A_START @private = 0xcbf29ce484222325;
const FNV64A_MUL @private = 0x00000100000001b3;
const Fnv64a FNV64A_START @private = (Fnv64a)0xcbf29ce484222325;
const Fnv64a FNV64A_MUL @private = (Fnv64a)0x00000100000001b3;
macro void update(h, char x) @private => *h = (*h ^ ($typeof(*h))x) * FNV64A_MUL;
macro Fnv64a update(Fnv64a h, char x) @nodiscard @private => (h ^ (Fnv64a)x) * FNV64A_MUL;
fn void Fnv64a.init(&self)
{
@@ -20,22 +20,22 @@ fn void Fnv64a.update(&self, char[] data)
Fnv64a h = *self;
foreach (char x : data)
{
update(&h, x);
h = update(h, x);
}
*self = h;
}
macro void Fnv64a.update_char(&self, char c)
{
update(self, c);
*self = update(*self, c);
}
fn ulong hash(char[] data)
{
ulong h = FNV64A_START;
Fnv64a h = FNV64A_START;
foreach (char x : data)
{
update(&h, x);
h = update(h, x);
}
return h;
return (ulong)h;
}

View File

@@ -1,6 +1,6 @@
module std::os::win32 @if(env::WIN32) @link("shell32");
typedef Win32_REFKNOWNFOLDERID = Win32_KNOWNFOLDERID*;
alias Win32_REFKNOWNFOLDERID = Win32_KNOWNFOLDERID*;
typedef Win32_KNOWNFOLDERID = Win32_GUID;
extern fn Win32_HRESULT shGetKnownFolderPath(Win32_REFKNOWNFOLDERID rfid, Win32_DWORD dwFlags, Win32_HANDLE hToken, Win32_PWSTR* ppszPath) @cname("SHGetKnownFolderPath");

View File

@@ -8,9 +8,9 @@ typedef NativeThread = int;
fn void NativeOnceFlag.call_once(&flag, OnceFn func)
{
if (*flag == 0)
if (*flag == (NativeOnceFlag)0)
{
*flag = 1;
*flag = (NativeOnceFlag)1;
func();
}
}

View File

@@ -12,6 +12,8 @@
- New const enum declaration syntax.
- New enum associated value syntax.
- Individual warning settings added.
- Change typedef and const enums to not convert from literals by default.
- Add `@constinit` to allow old typedef behaviour.
### Stdlib changes
- Summarize sort macros as generic function wrappers to reduce the amount of generated code. #2831

View File

@@ -717,6 +717,7 @@ typedef struct Decl_
bool resolved_attributes : 1;
bool allow_deprecated : 1;
bool attr_structlike : 1;
bool attr_constinit : 1;
bool is_template : 1;
bool is_templated : 1;
bool is_method_checked : 1;

View File

@@ -628,6 +628,7 @@ typedef enum
ATTRIBUTE_CNAME,
ATTRIBUTE_COMPACT,
ATTRIBUTE_CONST,
ATTRIBUTE_CONSTINIT,
ATTRIBUTE_DEPRECATED,
ATTRIBUTE_DYNAMIC,
ATTRIBUTE_EXPORT,

View File

@@ -1459,15 +1459,24 @@ static bool rule_to_distinct(CastContext *cc, bool is_explicit, bool is_silent)
{
is_const = true;
}
if (is_const && (cc->is_binary_conversion || !cc->to->decl->attr_structlike))
if (is_const && (cc->is_binary_conversion || cc->to->decl->attr_constinit || !cc->to->decl->attr_structlike))
{
Type *to_type = cc->to;
cc->to = flat;
cc->to_group = flat_group;
// If it's silent or explicit, just run it:
if (is_silent || is_explicit) return cast_is_allowed(cc, is_explicit, is_silent);
// Loud and implicit:
if (cast_is_allowed(cc, false, true)) return true;
if (cast_is_allowed(cc, false, true))
{
if (!cc->is_binary_conversion && !to_type->decl->attr_constinit && !expr_is_const_untyped_list(cc->expr))
{
to_type->decl->attr_constinit = true;
SEMA_DEPRECATED(cc->expr, "Implicit conversion of constants to distinct types is deprecated, use @constinit if %s should cast constants to its own type.", type_quoted_error_string(to_type));
}
return true;
}
return sema_cast_error(cc, cast_is_allowed(cc, true, true), is_silent);
}

View File

@@ -3128,6 +3128,7 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_
[ATTRIBUTE_CNAME] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES,
[ATTRIBUTE_COMPACT] = ATTR_STRUCT | ATTR_UNION,
[ATTRIBUTE_CONST] = ATTR_MACRO,
[ATTRIBUTE_CONSTINIT] = ATTR_TYPEDEF | ATTR_ENUM,
[ATTRIBUTE_DEPRECATED] = USER_DEFINED_TYPES | CALLABLE_TYPE | ATTR_CONST | ATTR_GLOBAL | ATTR_MEMBER | ATTR_BITSTRUCT_MEMBER | ATTR_INTERFACE | ATTR_ALIAS,
[ATTRIBUTE_DYNAMIC] = ATTR_FUNC,
[ATTRIBUTE_EXPORT] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES | ATTR_ALIAS,
@@ -3471,6 +3472,9 @@ static bool sema_analyse_attribute(SemaContext *context, ResolvedAttrData *attr_
case ATTRIBUTE_STRUCTLIKE:
decl->attr_structlike = true;
return true;
case ATTRIBUTE_CONSTINIT:
decl->attr_constinit = true;
return true;
case ATTRIBUTE_SIMD:
RETURN_SEMA_ERROR(attr, "'@simd' is only allowed on typedef types.");
case ATTRIBUTE_SECTION:

View File

@@ -347,6 +347,7 @@ void symtab_init(uint32_t capacity)
attribute_list[ATTRIBUTE_CNAME] = KW_DEF("@cname");
attribute_list[ATTRIBUTE_COMPACT] = KW_DEF("@compact");
attribute_list[ATTRIBUTE_CONST] = KW_DEF("@const");
attribute_list[ATTRIBUTE_CONSTINIT] = KW_DEF("@constinit");
attribute_list[ATTRIBUTE_DEPRECATED] = KW_DEF("@deprecated");
attribute_list[ATTRIBUTE_DYNAMIC] = KW_DEF("@dynamic");
attribute_list[ATTRIBUTE_EXPORT] = KW_DEF("@export");

View File

@@ -1,6 +1,6 @@
module test;
typedef Foo = int;
typedef Foo @constinit = int;
fn int test1()
{

View File

@@ -24,7 +24,7 @@ const enum Bde2 : int
BAR = 100
}
typedef Bde3 = int;
typedef Bde3 @constinit = int;
const BDE3_FOO = 2;
const BDE3_BAR = 100;