diff --git a/releasenotes.md b/releasenotes.md index 7a1a39748..fe86ef237 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -37,6 +37,7 @@ - Array indices are now using int64 internally. - Bit shift operation fails with inline uint enum despite matching underlying type #2279. - Fix to codegen when using a bitstruct constant defined using a cast with an operator #2248. +- Function pointers are now compile time constants. ### Stdlib changes - Improve contract for readline. #2280 diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index ae218449c..1b20d58eb 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -1675,7 +1675,7 @@ bool sema_analyse_const_enum_constant_val(SemaContext *context, Decl *decl) { Expr *value = decl->enum_constant.value; if (!sema_analyse_inferred_expr(context, decl->type, value)) return decl_poison(decl); - if (!sema_cast_const(value)) + if (!expr_is_runtime_const(value)) { SEMA_ERROR(value, "Expected an constant enum value."); return decl_poison(decl); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index e1cc4431e..850e2cc39 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -8366,9 +8366,11 @@ RESOLVED: if (no_optional->type_kind == TYPE_FUNC_RAW) { expr->type = type_add_optional(type_get_func_ptr(no_optional), IS_OPTIONAL((inner))); - return true; } - expr->type = type_get_ptr_recurse(inner->type); + else + { + expr->type = type_get_ptr_recurse(inner->type); + } if (inner->expr_kind == EXPR_IDENTIFIER) { Decl *ident = inner->ident_expr; diff --git a/test/test_suite/enumerations/const_enum_with_function_ptr.c3t b/test/test_suite/enumerations/const_enum_with_function_ptr.c3t new file mode 100644 index 000000000..83729ab90 --- /dev/null +++ b/test/test_suite/enumerations/const_enum_with_function_ptr.c3t @@ -0,0 +1,35 @@ +// #target: macos-x64 +module test; +import std; +fn int foo() => 0; +alias FooFn = fn int(); + +enum Foo : (FooFn f) +{ + FOO = fn int() => 0, // allowed + BAR = &foo, // allowed +} + +enum Bar : const FooFn +{ + FOO = fn int() => 0, // allowed + BAR = &foo, // Error: Expected an constant enum value. +} +fn int main() +{ + Bar b = FOO; + Bar b2 = BAR; + var $c = &foo == &foo; + return 0; +} + +/* #expect: test.ll + +define i32 @main() #0 { +entry: + %b = alloca ptr, align 8 + %b2 = alloca ptr, align 8 + store ptr @"test.$global$lambda2", ptr %b, align 8 + store ptr @test.foo, ptr %b2, align 8 + ret i32 0 +}