From da25a411f90303156efea95a787fd722649a418c Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Fri, 30 May 2025 19:12:08 +0200 Subject: [PATCH] Generic faults is disallowed. --- releasenotes.md | 1 + src/compiler/semantic_analyser.c | 5 ++++- test/test_suite/functions/test_regression.c3t | 2 -- .../functions/test_regression_mingw.c3t | 2 -- test/test_suite/generic/generic_fault.c3t | 11 +++++++++++ .../generic/generic_lambda_complex.c3t | 18 ++++++++++-------- .../switch/switch_in_defer_macro.c3t | 16 ++++++++++------ 7 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 test/test_suite/generic/generic_fault.c3t diff --git a/releasenotes.md b/releasenotes.md index c6960585d..ef7f0bcf3 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -25,6 +25,7 @@ - Allow recursive generic modules. - Add deprecation for `@param foo "abc"`. - Add `--header-output` and `header-output` options for controlling header output folder. +- Generic faults is disallowed. ### Fixes - Assert triggered when casting from `int[2]` to `uint[2]` #2115 diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index fd32f7d5c..3f529c52e 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -237,6 +237,10 @@ static void register_generic_decls(CompilationUnit *unit, Decl **decls) continue; case DECL_ATTRIBUTE: break; + case DECL_FAULT: + PRINT_ERROR_AT(decl, "Generic modules cannot use 'faultdef', place the declaration in a separate sub module or parent module instead."); + decl_poison(decl); + break; case DECL_BODYPARAM: case DECL_GROUP: UNREACHABLE @@ -247,7 +251,6 @@ static void register_generic_decls(CompilationUnit *unit, Decl **decls) case DECL_TYPEDEF: case DECL_UNION: case DECL_VAR: - case DECL_FAULT: case DECL_BITSTRUCT: case DECL_INTERFACE: break; diff --git a/test/test_suite/functions/test_regression.c3t b/test/test_suite/functions/test_regression.c3t index c44a9c41d..af54c6e56 100644 --- a/test/test_suite/functions/test_regression.c3t +++ b/test/test_suite/functions/test_regression.c3t @@ -201,8 +201,6 @@ fn Type getMult(Type a) } Type argh = 234; -faultdef X, Y; - enum Hello : int { FOO, diff --git a/test/test_suite/functions/test_regression_mingw.c3t b/test/test_suite/functions/test_regression_mingw.c3t index 1cd43607f..7a2f92389 100644 --- a/test/test_suite/functions/test_regression_mingw.c3t +++ b/test/test_suite/functions/test_regression_mingw.c3t @@ -203,8 +203,6 @@ fn Type getMult(Type a) } Type argh = 234; -faultdef X, Y; - enum Hello : int { FOO, diff --git a/test/test_suite/generic/generic_fault.c3t b/test/test_suite/generic/generic_fault.c3t new file mode 100644 index 000000000..2782097a0 --- /dev/null +++ b/test/test_suite/generic/generic_fault.c3t @@ -0,0 +1,11 @@ +module abc {Type}; + +attrdef @Hello = @inline; +faultdef ABC; // #error: Generic modules cannot use 'faultdef' + +module bcd; + +fn void main() +{ + Abc{int} a; +} \ No newline at end of file diff --git a/test/test_suite/generic/generic_lambda_complex.c3t b/test/test_suite/generic/generic_lambda_complex.c3t index 760c6e37a..e9f6fbc9a 100644 --- a/test/test_suite/generic/generic_lambda_complex.c3t +++ b/test/test_suite/generic/generic_lambda_complex.c3t @@ -1,13 +1,15 @@ // #target: macos-x64 +module abc_faults; + +faultdef UNTERMINATED_TAG, EMPTY_TAG, MISSING_TAG, UNSUPPORTED_TAG; + <* @require Type.kindof == STRUCT *> module abc{Type}; -import std::io; -import std::collections::list; +import std::io, abc_faults, std::collections::list; alias TextTagList = List{TextTag}; -faultdef UNTERMINATED_TAG, EMPTY_TAG, MISSING_TAG, UNSUPPORTED_TAG; enum TextTagKind: char { @@ -50,9 +52,9 @@ fn void? TextTemplate.init(&self, String template, String tag_start = "{{", Stri tmpl = tmpl[start + tag_start.len..]; usz? end = tmpl.index_of(tag_end); - if (catch end) return UNTERMINATED_TAG?; + if (catch end) return abc_faults::UNTERMINATED_TAG?; String name = tmpl[:end].trim(); - if (name == "") return EMPTY_TAG?; + if (name == "") return abc_faults::EMPTY_TAG?; // Check that the tag exists in the data struct. TextTag tag @noinit; @@ -80,7 +82,7 @@ fn void? TextTemplate.init(&self, String template, String tag_start = "{{", Stri //return UNSUPPORTED_TAG?; } $endforeach - return MISSING_TAG?; + return abc_faults::MISSING_TAG?; }; tmpl = tmpl[end + tag_end.len..]; @@ -201,7 +203,7 @@ panic_block: ; preds = %assign_optional %4 = insertvalue %"any[]" undef, ptr %varargslots, 0 %"$$temp" = insertvalue %"any[]" %4, i64 1, 1 store %"any[]" %"$$temp", ptr %indirectarg1, align 8 - call void @std.core.builtin.panicf(ptr @.panic_msg, i64 36, ptr @.file, i64 25, ptr @.func, i64 4, i32 159, ptr byval(%"any[]") align 8 %indirectarg1) #3 + call void @std.core.builtin.panicf(ptr @.panic_msg, unreachable noerr_block: ; preds = %after_check @@ -224,7 +226,7 @@ panic_block6: ; preds = %assign_optional4 %9 = insertvalue %"any[]" undef, ptr %varargslots7, 0 %"$$temp8" = insertvalue %"any[]" %9, i64 1, 1 store %"any[]" %"$$temp8", ptr %indirectarg9, align 8 - call void @std.core.builtin.panicf(ptr @.panic_msg, i64 36, ptr @.file, i64 25, ptr @.func, i64 4, i32 160, ptr byval(%"any[]") align 8 %indirectarg9) #3 + call void @std.core.builtin.panicf(ptr @.panic_msg, i64 36, unreachable noerr_block10: ; preds = %after_check5 diff --git a/test/test_suite/switch/switch_in_defer_macro.c3t b/test/test_suite/switch/switch_in_defer_macro.c3t index e547c3697..7db31f1ad 100644 --- a/test/test_suite/switch/switch_in_defer_macro.c3t +++ b/test/test_suite/switch/switch_in_defer_macro.c3t @@ -1,5 +1,10 @@ // #target: macos-x64 +module lexer::faults; + +faultdef UNTERMINATED_STRING, UNTERMINATED_RUNE, UNTERMINATED_COMMENT; +faultdef TRIE_FULL; + <* @require Token.kindof == ENUM && $typefrom(Token.inner).kindof == UNSIGNED_INT @require $defined((Token){}.token) @@ -19,7 +24,6 @@ enum Kind : char IDENTIFIER, } -faultdef UNTERMINATED_STRING, UNTERMINATED_RUNE, UNTERMINATED_COMMENT; alias TokenTrie = Trie{Token, ushort}; @@ -316,7 +320,7 @@ fn char? Lexer.parse_rune(&self) @private { char x = self.reader.read_byte()!; char c = self.reader.read_byte()!; - if (c != '\'') return UNTERMINATED_RUNE?; + if (c != '\'') return faults::UNTERMINATED_RUNE?; return x; } @@ -325,7 +329,7 @@ macro char? Lexer.read_char_for_string(&self) @private char? c = self.reader.read_byte(); if (catch err = c) { - if (err == io::EOF) return UNTERMINATED_STRING?; + if (err == io::EOF) return faults::UNTERMINATED_STRING?; return err?; } return c; @@ -350,7 +354,7 @@ fn void? Lexer.parse_comment(&self, String end) @private { if (catch err = io::read_all(self.reader, buf)) { - if (err == io::UNEXPECTED_EOF || err == io::EOF) return UNTERMINATED_COMMENT?; + if (err == io::UNEXPECTED_EOF || err == io::EOF) return faults::UNTERMINATED_COMMENT?; return err?; } if (end == (String)buf) @@ -455,11 +459,11 @@ fn int main(String[] args) module trie{Value, Index}; import std::collections::list; import trie::bitmap; +import lexer::faults; alias TrieNodeList = List{TrieNode}; alias TriePath @private = List{Index}; -faultdef TRIE_FULL; struct Trie { @@ -566,7 +570,7 @@ fn void? TrieNode.set(&self, Trie *t, char[] key, Value value) @private { usz new_idx = t.nodes.len(); assert(new_idx != 0); - if (new_idx > Index.max) return TRIE_FULL?; + if (new_idx > Index.max) return faults::TRIE_FULL?; idx = (Index)new_idx; self.children[c] = idx; t.nodes.push((TrieNode){});