diff --git a/lib/std/collections/maybe.c3 b/lib/std/collections/maybe.c3 index 9e51c3e70..948a01eb5 100644 --- a/lib/std/collections/maybe.c3 +++ b/lib/std/collections/maybe.c3 @@ -1,16 +1,43 @@ module std::collections::maybe(); +import std::io; -struct Maybe +struct Maybe (Printable) { Type value; bool has_value; } +fn usz! Maybe.to_format(&self, Formatter* f) @dynamic +{ + if (self.has_value) return f.printf("[%s]", self.value); + return f.printf("[EMPTY]"); +} + +fn void Maybe.set(&self, Type val) +{ + *self = { .value = val, .has_value = true }; +} + +fn void Maybe.reset(&self) +{ + *self = {}; +} + fn Maybe value(Type val) { return { .value = val, .has_value = true }; } +fn Maybe Maybe.with_value(Type val) @operator(construct) +{ + return { .value = val, .has_value = true }; +} + +fn Maybe Maybe.empty() @operator(construct) +{ + return { }; +} + const Maybe EMPTY = { }; macro Type! Maybe.get(self) diff --git a/releasenotes.md b/releasenotes.md index 94a09ad11..33070e2b9 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -17,6 +17,7 @@ - Allow using 'var' to declare lambdas in functions. - Add 'validation' setting and make dead code a warning. - Allow compile time `$foreach` iteration over constant Strings and bytes. +- Improved error message when accessing `@private` from other modules #1769. ### Fixes - Fix case trying to initialize a `char[*]*` from a String. @@ -62,6 +63,7 @@ - Add `@enum_from_value`. - Updated hash function. - Added URL parser. +- Added convenience functions to `Maybe`. ## 0.6.5 Change list diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index 17eaa44a6..31b674ecf 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -136,7 +136,7 @@ static inline Decl *sema_find_decl_in_module(Module *module, Path *path, const c return module_find_symbol(module, symbol); } -static bool sema_find_decl_in_private_imports(SemaContext *context, NameResolve *name_resolve, bool want_generic) +static bool sema_find_decl_in_imports(SemaContext *context, NameResolve *name_resolve, bool want_generic) { Decl *decl = NULL; // 1. Loop over imports. @@ -145,7 +145,8 @@ static bool sema_find_decl_in_private_imports(SemaContext *context, NameResolve FOREACH(Decl *, import, context->unit->imports) { if (import->import.module->is_generic != want_generic) continue; - if (!import->import.import_private_as_public) continue; + bool is_private_import = import->import.import_private_as_public; + if (!path && (decl || !is_private_import)) continue; // Is the decl in the import. Decl *found = sema_find_decl_in_module(import->import.module, path, symbol, &name_resolve->path_found); @@ -154,6 +155,16 @@ static bool sema_find_decl_in_private_imports(SemaContext *context, NameResolve ASSERT0(found->visibility != VISIBLE_LOCAL); + if (found->visibility != VISIBLE_PUBLIC) + { + if (decl) continue; + if (!is_private_import) + { + name_resolve->private_decl = found; + continue; + } + } + // Did we already have a match? if (decl) { @@ -418,7 +429,7 @@ static bool sema_resolve_path_symbol(SemaContext *context, NameResolve *name_res } // 3. Loop over imports. - if (!sema_find_decl_in_private_imports(context, name_resolve, false)) return false; + if (!sema_find_decl_in_imports(context, name_resolve, false)) return false; // 4. Go to global search if (name_resolve->found) return true; @@ -493,7 +504,7 @@ static bool sema_resolve_no_path_symbol(SemaContext *context, NameResolve *name_ return true; } - if (!sema_find_decl_in_private_imports(context, name_resolve, false)) return false; + if (!sema_find_decl_in_imports(context, name_resolve, false)) return false; if (name_resolve->found) return true; return sema_find_decl_in_global(context, &compiler.context.symbols, NULL, name_resolve, false); @@ -582,12 +593,12 @@ static void sema_report_error_on_decl(SemaContext *context, NameResolve *name_re const char *private_name = decl_to_name(name_resolve->private_decl); if (path_name) { - sema_error_at(context, span, "The %s '%s::%s' is not visible from this module.", + sema_error_at(context, span, "The %s '%s::%s' is '@private' and not visible from other modules.", private_name, path_name, symbol); } else { - sema_error_at(context, span, "The %s '%s' is not visible from this module.", + sema_error_at(context, span, "The %s '%s' is '@private' and not visible from other modules.", private_name, symbol); } return; @@ -982,7 +993,7 @@ bool unit_resolve_parameterized_symbol(SemaContext *context, NameResolve *name_r name_resolve->private_decl = NULL; name_resolve->path_found = NULL; - if (!sema_find_decl_in_private_imports(context, name_resolve, true)) return false; + if (!sema_find_decl_in_imports(context, name_resolve, true)) return false; if (!name_resolve->found) { if (!sema_find_decl_in_global(context, &compiler.context.generic_symbols, diff --git a/test/test_suite/visibility/not_visible.c3t b/test/test_suite/visibility/not_visible.c3t index cf882e145..d4cc2875d 100644 --- a/test/test_suite/visibility/not_visible.c3t +++ b/test/test_suite/visibility/not_visible.c3t @@ -4,7 +4,7 @@ import bar; fn void runBar() { - bar::notVisible(); // #error: 'bar::notVisible' could not be found + bar::notVisible(); // #error: 'bar::notVisible' is '@private' } // #file: file2.c3 diff --git a/test/test_suite/visibility/private_import.c3 b/test/test_suite/visibility/private_import.c3 index 6c1e7427d..16fa409e7 100644 --- a/test/test_suite/visibility/private_import.c3 +++ b/test/test_suite/visibility/private_import.c3 @@ -9,7 +9,7 @@ import foo; fn void test() { - foo::hidden(); // #error: 'foo::hidden' could not be found, + foo::hidden(); // #error: 'foo::hidden' is '@private' } module baz; diff --git a/test/test_suite/visibility/private_import2.c3 b/test/test_suite/visibility/private_import2.c3 index b727d57e1..b3032e6ee 100644 --- a/test/test_suite/visibility/private_import2.c3 +++ b/test/test_suite/visibility/private_import2.c3 @@ -22,6 +22,6 @@ import test; fn void abc() { - test::bar(); // #error: could not be found + test::bar(); // #error: is '@private' test::bar2(); // #error: could not be found } \ No newline at end of file