From 6bc606a9b1de175f6610be8fe921b7a5ea0835a5 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 2 Feb 2026 12:20:34 +0100 Subject: [PATCH] Removed analyse top pass. Remove sub module tracking. Fix errors where `?` should be `~` --- src/compiler/compiler_internal.h | 1 - src/compiler/enums.h | 1 - src/compiler/sema_expr.c | 10 +++---- src/compiler/sema_internal.h | 1 - src/compiler/sema_name_resolution.c | 4 +-- src/compiler/sema_passes.c | 27 ++++++++----------- src/compiler/semantic_analyser.c | 3 --- .../errors/optional_untyped_list.c3 | 2 +- .../errors/or_and_rethrow_missing_question.c3 | 2 +- .../from_docs/examples_if_catch.c3t | 2 +- 10 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index dd60c639f..98f19f27a 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1667,7 +1667,6 @@ typedef struct Module_ CompilationUnit **units; Module *parent_module; Module *top_module; - Module **sub_modules; Decl **benchmarks; Decl **tests; Decl **lambdas_to_evaluate; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 6380ec2a0..ffa47fd67 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -43,7 +43,6 @@ typedef enum { ANALYSIS_NOT_BEGUN, ANALYSIS_MODULE_HIERARCHY, - ANALYSIS_MODULE_TOP, ANALYSIS_IMPORTS, ANALYSIS_REGISTER_GLOBAL_DECLARATIONS, ANALYSIS_INCLUDES, diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index cd861b1e7..76e4393e6 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -9680,7 +9680,7 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr, CHECK_ON_DEFINED(failed_ref); if (else_type == type_fault) { - RETURN_SEMA_ERROR(right, "There is no common type for %s and %s, did you perhaps forget a '?' after the last expression?", type_quoted_error_string(type), type_quoted_error_string(else_type)); + RETURN_SEMA_ERROR(right, "There is no common type for %s and %s, did you perhaps forget a '~' after the last expression?", type_quoted_error_string(type), type_quoted_error_string(else_type)); } RETURN_SEMA_ERROR(right, "Cannot find a common type for %s and %s.", type_quoted_error_string(type), type_quoted_error_string(else_type)); } @@ -9965,7 +9965,7 @@ static inline bool sema_expr_analyse_optional(SemaContext *context, Expr *expr, if (inner->expr_kind == EXPR_OPTIONAL) { if (failed_ref) goto ON_FAILED; - RETURN_SEMA_ERROR(inner, "It looks like you added one too many '?' after the error."); + RETURN_SEMA_ERROR(inner, "It looks like you added one too many '~' after the error."); } Type *type = inner->type->canonical; @@ -9973,7 +9973,7 @@ static inline bool sema_expr_analyse_optional(SemaContext *context, Expr *expr, if (type != type_fault) { if (failed_ref) goto ON_FAILED; - RETURN_SEMA_ERROR(inner, "You cannot use the '?' operator on expressions of type %s", + RETURN_SEMA_ERROR(inner, "You cannot use the '~' operator on expressions of type %s", type_quoted_error_string(type)); } ASSERT_SPAN(expr, type->type_kind == TYPE_ANYFAULT || type->decl->resolve_status == RESOLVE_DONE); @@ -11696,7 +11696,7 @@ static inline bool sema_expr_analyse_compound_literal(SemaContext *context, Expr Type *type = type_info->type; if (type_is_optional(type)) { - RETURN_SEMA_ERROR(type_info, "The type here should always be written as a plain type and not an optional, please remove the '?'."); + RETURN_SEMA_ERROR(type_info, "The type here should always be written as a plain type and not an optional, please remove the '~'."); } if (!sema_resolve_type_structure(context, type)) return false; if (!sema_expr_analyse_initializer_list(context, type, expr->expr_compound_literal.initializer, no_match_ref)) return false; @@ -11975,7 +11975,7 @@ bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allo if (flat != type_fault && sema_cast_const(expr)) { if (no_match_ref) goto NO_MATCH_REF; - print_error_after(expr->span, "You need to add a trailing '?' here to make this an optional."); + print_error_after(expr->span, "You need to add a trailing '~' here to make this an optional."); return false; } } diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index 6c681da40..9483db36c 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -73,7 +73,6 @@ void sema_append_contract_asserts(AstId assert_first, Ast* compound_stmt); Decl *sema_create_runner_main(SemaContext *context, Decl *decl); -void sema_analyse_pass_top(Module *module); void sema_analyse_pass_module_hierarchy(Module *module); void sema_analysis_pass_process_imports(Module *module); void sema_analysis_pass_register_global_declarations(Module *module); diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index 1134cc3f2..60a955b4e 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -228,13 +228,11 @@ Decl *sema_find_decl_in_modules(Module **module_list, Path *path, const char *in INLINE bool module_inclusion_match(Module *a, Module *b) { - Module *temp; - // Quick check if (a->top_module != b->top_module) return false; if (a->name->len < b->name->len) { - temp = a; + Module *temp = a; a = b; b = temp; } diff --git a/src/compiler/sema_passes.c b/src/compiler/sema_passes.c index 99098c080..d481b450f 100644 --- a/src/compiler/sema_passes.c +++ b/src/compiler/sema_passes.c @@ -18,13 +18,6 @@ void parent_path(StringSlice *slice) slice->len = 0; } -void sema_analyse_pass_top(Module *module) -{ - Module *parent = module; - while (parent->parent_module) parent = parent->parent_module; - module->top_module = parent; -} - void sema_analyse_pass_module_hierarchy(Module *module) { const char *name = module->name->module; @@ -42,11 +35,9 @@ void sema_analyse_pass_module_hierarchy(Module *module) Path *checked_name = checked->name; if (checked_name->len != slice.len) continue; // Found the parent! We're done, we add this parent - // and this as a child. if (memcmp(checked_name->module, slice.ptr, slice.len) == 0) { module->parent_module = checked; - vec_add(checked->sub_modules, module); return; } } @@ -55,12 +46,17 @@ void sema_analyse_pass_module_hierarchy(Module *module) DEBUG_LOG("Creating parent module for %s: %s", module->name->module, path->module); Module *parent_module = compiler_find_or_create_module(path); module->parent_module = parent_module; - vec_add(parent_module->sub_modules, module); sema_analyze_stage(parent_module, ANALYSIS_MODULE_HIERARCHY); } void sema_analysis_pass_process_imports(Module *module) { + DEBUG_LOG("Pass: Set the top module '%s'.", module->name->module); + + Module *parent = module; + while (parent->parent_module) parent = parent->parent_module; + module->top_module = parent; + DEBUG_LOG("Pass: Importing dependencies for files in module '%s'.", module->name->module); unsigned total_import_count = 0; @@ -167,18 +163,17 @@ static bool sema_check_if_implicit_generic(SemaContext *context, Decl *decl) { if (!decl->func_decl.type_parent) return false; TypeInfo *typedecl = type_infoptr(decl->func_decl.type_parent); - Decl *d = NULL; if (typedecl->resolve_status == RESOLVE_DONE) { CanonicalType *type = typedecl->type->canonical; - if (!type_is_user_defined(type)) return false; - d = type->decl; + return type_is_user_defined(type) && type->decl->is_template; } - else if (typedecl->kind == TYPE_INFO_IDENTIFIER && typedecl->subtype == TYPE_COMPRESSED_NONE) + if (typedecl->kind == TYPE_INFO_IDENTIFIER && typedecl->subtype == TYPE_COMPRESSED_NONE) { - d = sema_resolve_maybe_parameterized_symbol(context, typedecl->unresolved.name, typedecl->unresolved.path, typedecl->span); + Decl *d = sema_resolve_maybe_parameterized_symbol(context, typedecl->unresolved.name, typedecl->unresolved.path, typedecl->span); + return d && d->is_template; // NOLINT because apparently this is not checking for NULL!? } - return d && d->is_template; + return false; } void unit_register_optional_global_decl(CompilationUnit *unit, Decl *decl) diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index e5e8a3ccb..406e144e5 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -174,9 +174,6 @@ void sema_analyze_stage(Module *module, AnalysisStage stage) case ANALYSIS_MODULE_HIERARCHY: sema_analyse_pass_module_hierarchy(module); break; - case ANALYSIS_MODULE_TOP: - sema_analyse_pass_top(module); - break; case ANALYSIS_IMPORTS: sema_analysis_pass_process_imports(module); break; diff --git a/test/test_suite/errors/optional_untyped_list.c3 b/test/test_suite/errors/optional_untyped_list.c3 index 25abb62c4..0549dec05 100644 --- a/test/test_suite/errors/optional_untyped_list.c3 +++ b/test/test_suite/errors/optional_untyped_list.c3 @@ -25,5 +25,5 @@ fn void foo2() fn void test() { int? z = 2; - Foo*? w = &&(Foo?){ z, 0 }; // #error: please remove the '?' + Foo*? w = &&(Foo?){ z, 0 }; // #error: please remove the '~' } \ No newline at end of file diff --git a/test/test_suite/errors/or_and_rethrow_missing_question.c3 b/test/test_suite/errors/or_and_rethrow_missing_question.c3 index b729a0cb8..1315b1bc0 100644 --- a/test/test_suite/errors/or_and_rethrow_missing_question.c3 +++ b/test/test_suite/errors/or_and_rethrow_missing_question.c3 @@ -18,7 +18,7 @@ fn int main(String[] args) if (catch foo) { // This is issue 2036 - foo = foo ?? faults::DISTRACTED_BY_CAT_PICTURES; // #error: did you perhaps forget a '?' + foo = foo ?? faults::DISTRACTED_BY_CAT_PICTURES; // #error: did you perhaps forget a '~' } return 0; diff --git a/test/test_suite/from_docs/examples_if_catch.c3t b/test/test_suite/from_docs/examples_if_catch.c3t index 2d92e2957..4b0af7d4c 100644 --- a/test/test_suite/from_docs/examples_if_catch.c3t +++ b/test/test_suite/from_docs/examples_if_catch.c3t @@ -15,7 +15,7 @@ fn double? divide(int a, int b) } -// Rethrowing an error uses "?" suffix +// Rethrowing an error uses "!" suffix fn void? testMayError() { divide(foo(), bar())!;