- Empty enums would return the values as zero sized arrays #2838

This commit is contained in:
Christoffer Lerno
2026-01-25 04:41:06 +01:00
parent 0fdd6bdc81
commit 109e15b5a0
8 changed files with 43 additions and 26 deletions

View File

@@ -1,5 +1,6 @@
<*
@require Enum.kindof == TypeKind.ENUM : "Only enums may be used with an enummap"
@require Enum.values.len > 0 : "Only non-empty enums may be used with enummap"
*>
module std::collections::enummap <Enum, ValueType>;
import std::io;

View File

@@ -1,16 +1,13 @@
// Copyright (c) 2025 Zack Puhl <github@xmit.xyz>. All rights reserved.
// Use of this source code is governed by the MIT license
// a copy of which can be found in the LICENSE_STDLIB file.
<*
@require @in(DIGEST_BITS, ...PERMISSIBLE_SIZES_BITS) : "Invalid DIGEST_BITS; must be one of {128, 160, 256, 320}."
*>
module std::hash::ripemd <DIGEST_BITS>;
module std::hash::ripemd;
const usz[4] PERMISSIBLE_SIZES_BITS = { 128, 160, 256, 320 };
<* Unchanging block size. *>
const BLOCK_SIZE = 64;
const usz[4] PERMISSIBLE_SIZES_BITS = { 128, 160, 256, 320 };
<* RIPE-MD initial values. *>
const uint[10] H = {
@@ -24,6 +21,11 @@ const uint[9] K = {
0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9
};
<*
@require @in(DIGEST_BITS, ...PERMISSIBLE_SIZES_BITS) : "Invalid DIGEST_BITS; must be one of {128, 160, 256, 320}."
*>
module std::hash::ripemd <DIGEST_BITS>;
<* Ultimate digest's size in bytes. *>
const DIGEST_BYTES = DIGEST_BITS / 8;

View File

@@ -124,6 +124,7 @@
- Constant deref of subscript had inserted checks #2818
- Raw vaargs with optional return not lowered correctly #2819
- Early exit in macro call crashes codegen #2820
- Empty enums would return the values as zero sized arrays #2838
### Stdlib changes
- Add `ThreadPool` join function to wait for all threads to finish in the pool without destroying the threads.

View File

@@ -5293,14 +5293,6 @@ FOUND:;
vec_add(generic->generic_decl.instances, instance);
AnalysisStage stage = module->stage;
ASSERT(stage > ANALYSIS_IMPORTS);
// Add all the normal top level declarations
FOREACH(Decl *, decl, copied) unit_register_global_decl(decl->unit, decl);
// Add all the conditional declarations
FOREACH(Decl *, decl, copied_cond)
{
unit_register_optional_global_decl(decl->unit, decl);
if (decl->decl_kind != DECL_ERASED) vec_add(copied, decl);
}
if (compiler.context.errors_found) return poisoned_decl;
// Check contracts
@@ -5316,11 +5308,22 @@ FOUND:;
SourceSpan param_span = extend_span_with_token(params[0]->span, VECLAST(params)->span);
if (!sema_analyse_generic_module_contracts(context, module, instance, contracts, param_span, invocation_span))
{
return poisoned_decl;
decl_poison(instance);
decl_poison(alias);
return alias;
}
}
}
// Add all the normal top level declarations
FOREACH(Decl *, decl, copied) unit_register_global_decl(decl->unit, decl);
// Add all the conditional declarations
FOREACH(Decl *, decl, copied_cond)
{
unit_register_optional_global_decl(decl->unit, decl);
if (decl->decl_kind != DECL_ERASED) vec_add(copied, decl);
}
if (stage < ANALYSIS_METHODS_REGISTER) goto EXIT;
FOREACH(Decl *, decl, copied)
{

View File

@@ -4962,7 +4962,7 @@ static inline bool sema_expr_replace_with_enum_array(SemaContext *context, Expr
initializer->initializer_list = element_values;
enum_array_expr->expr_kind = EXPR_COMPOUND_LITERAL;
enum_array_expr->expr_compound_literal.initializer = initializer;
enum_array_expr->expr_compound_literal.type_info = type_info_new_base(type_get_array(kind, elements), span);
enum_array_expr->expr_compound_literal.type_info = type_info_new_base(type_get_slice(kind), span);
enum_array_expr->resolve_status = RESOLVE_NOT_DONE;
return sema_analyse_expr_rvalue(context, enum_array_expr);
}
@@ -4985,7 +4985,7 @@ static inline bool sema_expr_replace_with_const_enum_array(SemaContext *context,
initializer->initializer_list = element_values;
enum_array_expr->expr_kind = EXPR_COMPOUND_LITERAL;
enum_array_expr->expr_compound_literal.initializer = initializer;
enum_array_expr->expr_compound_literal.type_info = type_info_new_base(type_get_array(kind, elements), span);
enum_array_expr->expr_compound_literal.type_info = type_info_new_base(type_get_slice(kind), span);
enum_array_expr->resolve_status = RESOLVE_NOT_DONE;
return sema_analyse_expr_rvalue(context, enum_array_expr);
}

View File

@@ -0,0 +1,6 @@
import std;
enum Foo
{
}
EnumMap{Foo, int} map; // #error: Parameter(s) would violate constraint: @require "Enum.values.len > 0" violated
fn int main() => 1;

View File

@@ -9,7 +9,7 @@ enum Foo
}
Foo zfok = Foo.values[0];
Foo[] zw = &&Foo.values;
Foo[] zw = Foo.values;
fn void test(int x)
{
@@ -19,17 +19,21 @@ fn void test(int x)
/* #expect: test.ll
@test.zfok = local_unnamed_addr global i32 0, align 4
@.taddr = private unnamed_addr global [2 x i32] [i32 0, i32 1], align 4
@test.zw = local_unnamed_addr global %"int[]" { ptr @.taddr, i64 2 }, align 8
@.__const_slice = private unnamed_addr global [2 x i32] [i32 0, i32 1], align 4
@test.zw = local_unnamed_addr global %"int[]" { ptr @.__const_slice, i64 2 }, align 8
@.__const = private unnamed_addr constant [2 x i32] [i32 0, i32 1], align 4
define void @test.test(i32 %0) #0 {
entry:
%zonk = alloca i32, align 4
%literal = alloca [2 x i32], align 4
call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const, i32 8, i1 false)
%1 = insertvalue %"int[]" undef, ptr %literal, 0
%2 = insertvalue %"int[]" %1, i64 2, 1
%3 = extractvalue %"int[]" %2, 0
%sext = sext i32 %0 to i64
%ptroffset = getelementptr inbounds [4 x i8], ptr %literal, i64 %sext
%1 = load i32, ptr %ptroffset, align 4
store i32 %1, ptr %zonk, align 4
%ptroffset = getelementptr inbounds [4 x i8], ptr %3, i64 %sext
%4 = load i32, ptr %ptroffset, align 4
store i32 %4, ptr %zonk, align 4
ret void
}

View File

@@ -48,7 +48,7 @@ fn void basic_streamed()
x'e7660e67549435c62141e51c9ab1dcc3b1ee9f65c0b3e561ae8f58c5dba3d21997781cd1cc6fbc34'
};
char[] phrase = "The quick brown fox jumps over the lazy dog";
$foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS{128}:
$foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS:
{ // le scope
RipeMd{$bits} r @noinit;
r.init();
@@ -83,7 +83,7 @@ fn void large_input_streamed()
};
char[] one_mb = mem::talloc_array(char, 1024*1024);
one_mb[..] = 0xA5;
$foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS{128}:
$foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS:
{
RipeMd{$bits} r @noinit;
r.init();
@@ -106,7 +106,7 @@ fn void large_input_streamed_per_byte()
};
char[] one_mb = mem::talloc_array(char, 1024*1024);
one_mb[..] = 0xA5;
$foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS{128}:
$foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS:
{
RipeMd{$bits} r @noinit;
r.init();
@@ -132,7 +132,7 @@ fn void walk_lengths_streamed()
{
foreach (arr : CALCULATED_HASHES)
{
$foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS{128}:
$foreach $i, $bits : ripemd::PERMISSIBLE_SIZES_BITS:
{
RipeMd{$bits} r @noinit;
r.init();