diff --git a/STYLE.md b/STYLE.md index ba000774e..b2b1b4271 100644 --- a/STYLE.md +++ b/STYLE.md @@ -7,7 +7,7 @@ footguns, crashes, bugs, and UB. 1. All methods are `constexpr` unless they must call a non-`constexpr` function, or they expose floating point NaNs (since constexpr NaNs change their bit values). - * Consider `sus_panic()`/`sus_check()` as constexpr for these purposes, they will + * Consider `sus::panic()`/`sus_check()` as constexpr for these purposes, they will correctly prevent compiling if the condition fails. 1. If you override on `const&`, then explicitly provide or delete the `&&` override. @@ -71,7 +71,7 @@ footguns, crashes, bugs, and UB. `operator==(Option, Option)` and `operator==(Option, Option)` look redundant but they are not, as the former allows conversions to Option for the rhs to happen while the latter does not (it would have to deduce `U` and fails). - + ## Containers that hold references Container types that hold references require extra care in a number of ways. To @@ -87,13 +87,13 @@ properly build such a container type (e.g. `Option` and `Tuple`): from an rvalue is okay, but when holding a value, giving a reference to it from an rvalue is not. * Use `static_assert(SafelyConstructibleFromReference)` - in places that store the reference to ensure a reference to a temporary does not + in places that store the reference to ensure a reference to a temporary does not get created due to an implicit conversion. The `FromReferenceType&&` here is should be the input type as it's written in the function parameters. * If a ctor type deduction guide is provided, the deduction should strip qualifiers and references with `std::remove_cvref_t` on the deduced type arguments. * Consider providing a construction marker type such as `some() -> SomeMarker` which - captures the parameters as references and lazily constructs the final type. This + captures the parameters as references and lazily constructs the final type. This allows reference types to be preserved through to the construction of the container without requiring the full type defn to be written every time. * Notably, this is omitted for `Choice`, which needs to be reasonably used behind diff --git a/subdoc/lib/friendly_names.h b/subdoc/lib/friendly_names.h index d09fd9bdb..03a435f8a 100644 --- a/subdoc/lib/friendly_names.h +++ b/subdoc/lib/friendly_names.h @@ -67,7 +67,7 @@ inline std::string friendly_record_type_name(RecordType t, case RecordType::Struct: return capitalize ? "Struct" : "struct"; case RecordType::Union: return capitalize ? "Union" : "union"; } - sus_unreachable_unchecked(unsafe_fn); + sus::unreachable_unchecked(unsafe_fn); } } // namespace subdoc diff --git a/subdoc/lib/gen/files.h b/subdoc/lib/gen/files.h index 5c53a8958..c71fccddd 100644 --- a/subdoc/lib/gen/files.h +++ b/subdoc/lib/gen/files.h @@ -101,7 +101,7 @@ inline std::filesystem::path construct_html_namespace_file_path( return fmt::format("namespace.{}", namespace_path[0u].as()); } - sus_unreachable(); + sus::unreachable(); }(); fname << name; @@ -316,7 +316,7 @@ inline Option construct_html_url_for_alias( // aliases. break; } - sus_unreachable(); + sus::unreachable(); }); } case AliasTarget::Tag::AliasOfConcept: { @@ -330,11 +330,11 @@ inline Option construct_html_url_for_alias( } case ConceptRefOrName::Tag::Name: return sus::none(); } - sus_unreachable(); + sus::unreachable(); } case AliasTarget::Tag::AliasOfMethod: { // TODO: Link to method. - sus_unreachable(); + sus::unreachable(); } case AliasTarget::Tag::AliasOfFunction: { const LinkedFunction& fun = @@ -347,11 +347,11 @@ inline Option construct_html_url_for_alias( } case FunctionRefOrName::Tag::Name: return sus::none(); } - sus_unreachable(); + sus::unreachable(); } case AliasTarget::Tag::AliasOfEnumConstant: { // TODO: Link to constant. - sus_unreachable(); + sus::unreachable(); } case AliasTarget::Tag::AliasOfVariable: { const LinkedVariable& var = @@ -364,10 +364,10 @@ inline Option construct_html_url_for_alias( } case VariableRefOrName::Tag::Name: return sus::none(); } - sus_unreachable(); + sus::unreachable(); } } - sus_unreachable(); + sus::unreachable(); } else { // TODO: Link to the alias' page. return sus::some("TODO"); diff --git a/subdoc/lib/gen/generate.h b/subdoc/lib/gen/generate.h index f84edbfeb..6fa9de650 100644 --- a/subdoc/lib/gen/generate.h +++ b/subdoc/lib/gen/generate.h @@ -70,7 +70,7 @@ struct sus::error::ErrorImpl { return fmt::format("parsing doc comment markdown"); } } - sus_unreachable(); + sus::unreachable(); } static Option source( const GenerateError& e) noexcept { @@ -88,6 +88,6 @@ struct sus::error::ErrorImpl { return sus::some(*p); } } - sus_unreachable(); + sus::unreachable(); } }; diff --git a/subdoc/lib/gen/generate_alias.cc b/subdoc/lib/gen/generate_alias.cc index 524d49cbf..a9a9ee66d 100644 --- a/subdoc/lib/gen/generate_alias.cc +++ b/subdoc/lib/gen/generate_alias.cc @@ -77,7 +77,7 @@ sus::Result get_alias_comment( } case AliasTarget::Tag::AliasOfMethod: { // TODO: Link to method. - sus_unreachable(); + sus::unreachable(); } case AliasTarget::Tag::AliasOfFunction: { const LinkedFunction& fun = @@ -94,7 +94,7 @@ sus::Result get_alias_comment( } case AliasTarget::Tag::AliasOfEnumConstant: { // TODO: Link to constant. - sus_unreachable(); + sus::unreachable(); } case AliasTarget::Tag::AliasOfVariable: { const LinkedVariable& var = diff --git a/subdoc/lib/gen/generate_concept.cc b/subdoc/lib/gen/generate_concept.cc index 03a278027..6ea038468 100644 --- a/subdoc/lib/gen/generate_concept.cc +++ b/subdoc/lib/gen/generate_concept.cc @@ -77,7 +77,7 @@ void generate_concept_overview(HtmlWriter::OpenDiv& record_div, break; // Macro can't be an ancesor of a concept. case CppPathConcept: return "concept-name"; } - sus_unreachable(); + sus::unreachable(); }()); ancestor_anchor.add_href(e.link_href); ancestor_anchor.write_text(e.name); diff --git a/subdoc/lib/gen/generate_cpp_path.cc b/subdoc/lib/gen/generate_cpp_path.cc index 7682c08cb..7f17ac1ce 100644 --- a/subdoc/lib/gen/generate_cpp_path.cc +++ b/subdoc/lib/gen/generate_cpp_path.cc @@ -41,7 +41,7 @@ Vec generate_with_ancestors( return std::string("(anonymous)"); case Namespace::Tag::Named: return sus::clone(ancestor.name); } - sus_unreachable(); + sus::unreachable(); }(), .link_href = construct_html_url_for_namespace(ancestor), .type = @@ -51,7 +51,7 @@ Vec generate_with_ancestors( case Namespace::Tag::Anonymous: return CppPathNamespace; case Namespace::Tag::Named: return CppPathNamespace; } - sus_unreachable(); + sus::unreachable(); }(), .search_weight = 1_f32, }); diff --git a/subdoc/lib/gen/generate_function.cc b/subdoc/lib/gen/generate_function.cc index 87a6038b6..ad94f1cab 100644 --- a/subdoc/lib/gen/generate_function.cc +++ b/subdoc/lib/gen/generate_function.cc @@ -321,7 +321,7 @@ sus::Result generate_function( case CppPathConcept: break; // Concept can't be an ancestor of a function. } - sus_unreachable(); + sus::unreachable(); }()); ancestor_anchor.add_href(e.link_href); ancestor_anchor.write_text(e.name); diff --git a/subdoc/lib/gen/generate_macro.cc b/subdoc/lib/gen/generate_macro.cc index 68e2ce44c..b9d0079e1 100644 --- a/subdoc/lib/gen/generate_macro.cc +++ b/subdoc/lib/gen/generate_macro.cc @@ -145,7 +145,7 @@ sus::Result generate_macro( case CppPathProject: return "project-name"; case CppPathMacro: return "macro-name"; default: - sus_unreachable(); // Macros are only in the global namespace. + sus::unreachable(); // Macros are only in the global namespace. } }()); ancestor_anchor.add_href(e.link_href); diff --git a/subdoc/lib/gen/generate_namespace.cc b/subdoc/lib/gen/generate_namespace.cc index 4863a2d9a..851334602 100644 --- a/subdoc/lib/gen/generate_namespace.cc +++ b/subdoc/lib/gen/generate_namespace.cc @@ -196,7 +196,7 @@ void generate_namespace_overview(HtmlWriter::OpenDiv& namespace_div, case CppPathConcept: break; // Concept can't be an ancestor of a namespace. } - sus_unreachable(); + sus::unreachable(); }()); ancestor_anchor.add_href(e.link_href); ancestor_anchor.write_text(e.name); @@ -615,7 +615,7 @@ sus::Result generate_namespace( json.add_string("split_name", split_for_search(options.project_name)); break; } - case Namespace::Tag::Anonymous: sus_unreachable(); + case Namespace::Tag::Anonymous: sus::unreachable(); case Namespace::Tag::Named: { json.add_string("type", "namespace"); json.add_string("name", element.name); diff --git a/subdoc/lib/gen/generate_record.cc b/subdoc/lib/gen/generate_record.cc index 89f4ff0e3..9d2757708 100644 --- a/subdoc/lib/gen/generate_record.cc +++ b/subdoc/lib/gen/generate_record.cc @@ -64,7 +64,7 @@ const FunctionElement& function_element_from_sorted( case MethodType::NonStaticOperators: return element.methods.at(s.at<3>()); case MethodType::Conversions: return element.conversions.at(s.at<3>()); } - sus_unreachable(); + sus::unreachable(); } /// Compares two `SortedFunctionByName` for ordering. It compares by ignoring @@ -135,7 +135,7 @@ void generate_record_overview(HtmlWriter::OpenDiv& record_div, case CppPathConcept: break; // Concept can't be an ancestor of a record. } - sus_unreachable(); + sus::unreachable(); }()); ancestor_anchor.add_href(e.link_href); ancestor_anchor.write_text(e.name); diff --git a/subdoc/lib/requires.cc b/subdoc/lib/requires.cc index 2e9e97bb9..136f7941e 100644 --- a/subdoc/lib/requires.cc +++ b/subdoc/lib/requires.cc @@ -29,7 +29,7 @@ std::string template_arg_to_string(const clang::TemplateArgumentLoc& loc, // How can this happen in a concept instantiation? arg.dump(); fmt::println(""); - sus_unreachable(); + sus::unreachable(); case clang::TemplateArgument::ArgKind::Type: { if (arg.getAsType()->isDependentType()) { // A template argument that is a template parameter (from the function, @@ -43,7 +43,7 @@ std::string template_arg_to_string(const clang::TemplateArgumentLoc& loc, // How can this happen in a concept instantiation? arg.dump(); fmt::println(""); - sus_unreachable(); + sus::unreachable(); case clang::TemplateArgument::ArgKind::NullPtr: return "nullptr"; case clang::TemplateArgument::ArgKind::Integral: { return llvm_int_to_string(arg.getAsIntegral()); @@ -57,19 +57,19 @@ std::string template_arg_to_string(const clang::TemplateArgumentLoc& loc, // How can this happen in a concept instantiation? arg.dump(); fmt::println(""); - sus_unreachable(); + sus::unreachable(); case clang::TemplateArgument::ArgKind::TemplateExpansion: // How can this happen in a concept instantiation? arg.dump(); fmt::println(""); - sus_unreachable(); + sus::unreachable(); case clang::TemplateArgument::ArgKind::Expression: return stmt_to_string(*arg.getAsExpr(), context.getSourceManager(), preprocessor); case clang::TemplateArgument::ArgKind::Pack: return std::string("TODO: pack"); } - sus_unreachable(); + sus::unreachable(); }; void requires_constraints_add_expr(RequiresConstraints& constraints, diff --git a/subdoc/lib/type.cc b/subdoc/lib/type.cc index 59b8a6931..7aa7e8995 100644 --- a/subdoc/lib/type.cc +++ b/subdoc/lib/type.cc @@ -170,7 +170,7 @@ clang::DeclContext* find_context(const clang::Type* type, case clang::NestedNameSpecifier::Super: return spec->getAsRecordDecl()->getDeclContext(); } - sus_unreachable(); + sus::unreachable(); } else if (auto* tag_type = clang::dyn_cast(type)) { return tag_type->getDecl()->getDeclContext(); } else if (auto* spec_type = @@ -201,7 +201,7 @@ clang::DeclContext* find_context(const clang::Type* type, } else { type->dump(); loc.dump(sm); - sus_unreachable(); // Find the context. + sus::unreachable(); // Find the context. } } @@ -221,7 +221,7 @@ TypeOrValue build_template_param( arg.dump(); fmt::println(stderr, ""); loc.dump(sm); - sus_unreachable(); + sus::unreachable(); case clang::TemplateArgument::ArgKind::Type: return TypeOrValue(TypeOrValueChoice::with( build_local_type_internal(arg.getAsType(), template_params, cx, @@ -261,16 +261,16 @@ TypeOrValue build_template_param( arg.dump(); fmt::println(stderr, ""); loc.dump(sm); - sus_unreachable(); + sus::unreachable(); case clang::TemplateArgument::ArgKind::Expression: return TypeOrValue(TypeOrValueChoice::with( stmt_to_string(*arg.getAsExpr(), sm, preprocessor))); case clang::TemplateArgument::ArgKind::Pack: // Packs are handled at a higher level since they produce multiple types. loc.dump(sm); - sus_unreachable(); + sus::unreachable(); } - sus_unreachable(); + sus::unreachable(); }; clang::QualType unwrap_skipped_types(clang::QualType q) noexcept { @@ -348,7 +348,7 @@ Type build_local_type_internal( qualtype->dump(); loc.dump(sm); fmt::println(stderr, "\nkind: {}", (int)kind); - sus_unreachable(); + sus::unreachable(); } spec = spec->getPrefix(); } @@ -374,7 +374,7 @@ Type build_local_type_internal( if (is_pack) { qualtype->dump(); loc.dump(sm); - sus_unreachable(); + sus::unreachable(); } // Arrays come with the var name wrapped in parens, which must be removed. @@ -397,7 +397,7 @@ Type build_local_type_internal( if (auto* vararr = clang::dyn_cast(type)) { qualtype->dump(); loc.dump(sm); - sus_unreachable(); // This is a C thing, not C++. + sus::unreachable(); // This is a C thing, not C++. } // For arrays the root qualifiers come from the element type. @@ -496,7 +496,7 @@ Type build_local_type_internal( // Partial specialization in another type? partial->dump(); loc.dump(sm); - sus_unreachable(); + sus::unreachable(); } else if (auto* full = clang::dyn_cast( rec_type->getDecl())) { @@ -539,7 +539,7 @@ Type build_local_type_internal( // No template parameters. // qualtype->dump(); // loc.dump(sm); - // sus_unreachable(); + // sus::unreachable(); } // Find the context from which to collect the namespace/record paths. @@ -593,7 +593,7 @@ Type build_local_type_internal( if (auto_type->isConstrained()) { qualtype->dump(); loc.dump(sm); - sus_panic_with_message("constrained auto without a concept?"); + sus::panic("constrained auto without a concept?"); } if (auto_type->isDecltypeAuto()) { return sus::tuple("decltype(auto)", TypeCategory::TemplateVariable); diff --git a/subdoc/lib/visit.cc b/subdoc/lib/visit.cc index 45487e17e..2854045d2 100644 --- a/subdoc/lib/visit.cc +++ b/subdoc/lib/visit.cc @@ -720,7 +720,7 @@ class Visitor : public clang::RecursiveASTVisitor { // unit. decl->dump(); decl->getDeclContext()->dumpAsDecl(); - sus_unreachable(); + sus::unreachable(); } auto te = AliasElement( @@ -758,7 +758,7 @@ class Visitor : public clang::RecursiveASTVisitor { // unit. decl->dump(); decl->getDeclContext()->dumpAsDecl(); - sus_unreachable(); + sus::unreachable(); } auto te = AliasElement( @@ -797,7 +797,7 @@ class Visitor : public clang::RecursiveASTVisitor { // The context for a concept is a namespace or translation unit. decl->dump(); decl->getDeclContext()->dumpAsDecl(); - sus_unreachable(); + sus::unreachable(); } Vec target_namespaces = @@ -833,7 +833,7 @@ class Visitor : public clang::RecursiveASTVisitor { decl->getBeginLoc().dump(decl->getASTContext().getSourceManager()); // TODO: Put these into static fields on a record, and const global // variables on a namespace. - //sus_unreachable(); + //sus::unreachable(); } else if (auto* vardecl = clang::dyn_cast(shadow->getTargetDecl())) { auto* context = @@ -844,7 +844,7 @@ class Visitor : public clang::RecursiveASTVisitor { // can't write an alias to a static class data member. decl->dump(); decl->getDeclContext()->dumpAsDecl(); - sus_unreachable(); + sus::unreachable(); } Vec target_namespaces = @@ -881,7 +881,7 @@ class Visitor : public clang::RecursiveASTVisitor { // The context for a using method is a record. decl->dump(); decl->getDeclContext()->dumpAsDecl(); - sus_unreachable(); + sus::unreachable(); } auto te = AliasElement( @@ -926,7 +926,7 @@ class Visitor : public clang::RecursiveASTVisitor { // The context for a function is a namespace or translation unit. decl->dump(); decl->getDeclContext()->dumpAsDecl(); - sus_unreachable(); + sus::unreachable(); } Vec target_namespaces = @@ -966,7 +966,7 @@ class Visitor : public clang::RecursiveASTVisitor { // The context for a function is a namespace or translation unit. decl->dump(); decl->getDeclContext()->dumpAsDecl(); - sus_unreachable(); + sus::unreachable(); } Vec target_namespaces = @@ -1002,7 +1002,7 @@ class Visitor : public clang::RecursiveASTVisitor { decl->getBeginLoc().dump(decl->getASTContext().getSourceManager()); fmt::println(stderr, ""); shadow->getTargetDecl()->dump(); - sus_unreachable(); + sus::unreachable(); } } @@ -1342,7 +1342,7 @@ class Visitor : public clang::RecursiveASTVisitor { else return MethodQualifier::MutableRValue; } - sus_unreachable(); + sus::unreachable(); }(), }); } @@ -1775,7 +1775,7 @@ bool VisitCx::should_include_decl_based_on_file(clang::Decl* decl) noexcept { return true; } } - sus_unreachable(); + sus::unreachable(); } } // namespace subdoc diff --git a/subdoc/tests/cpp_version.h b/subdoc/tests/cpp_version.h index 57ee59772..620a8e48c 100644 --- a/subdoc/tests/cpp_version.h +++ b/subdoc/tests/cpp_version.h @@ -28,7 +28,7 @@ inline std::string_view cpp_version_flag(SubDocCppVersion v) noexcept { switch (v) { case SubDocCppVersion::Cpp20: return "-std=c++20"; } - sus_unreachable(); + sus::unreachable(); } } // namespace subdoc::tests diff --git a/sus/CMakeLists.txt b/sus/CMakeLists.txt index c52d372d3..982a7c569 100644 --- a/sus/CMakeLists.txt +++ b/sus/CMakeLists.txt @@ -327,6 +327,10 @@ if(${SUBSPACE_BUILD_TESTS}) "tuple/tuple_unittest.cc" ) + add_executable(subspace_panic_elide_message_unittest + "assertions/panic_unittest.cc" + ) + add_executable(subspace_overflow_unittests "num/i8_overflow_unittest.cc" "num/i16_overflow_unittest.cc" @@ -354,6 +358,18 @@ if(${SUBSPACE_BUILD_TESTS}) ) gtest_discover_tests(subspace_unittests) + # Subspace panic unittests + subspace_test_default_compile_options(subspace_panic_elide_message_unittest) + target_compile_options(subspace_panic_elide_message_unittest PUBLIC + -DSUS_PANIC_ELIDE_MESSAGE + ) + target_link_libraries(subspace_panic_elide_message_unittest + subspace::lib + subspace::test_support + gtest_main + ) + gtest_discover_tests(subspace_panic_elide_message_unittest) + # Subspace overflow unittests subspace_test_default_compile_options(subspace_overflow_unittests) target_compile_options(subspace_overflow_unittests PUBLIC @@ -366,4 +382,3 @@ if(${SUBSPACE_BUILD_TESTS}) ) gtest_discover_tests(subspace_overflow_unittests) endif() - diff --git a/sus/assertions/check.h b/sus/assertions/check.h index 582a6a8ba..063ce8dbd 100644 --- a/sus/assertions/check.h +++ b/sus/assertions/check.h @@ -17,32 +17,32 @@ #include "sus/assertions/panic.h" /// Verifies that the input, evaluated to a `bool`, is true. Otherwise, it will -/// [`panic`]($sus_panic), printing a message and terminating the program. +/// [`panic`]($sus::panic), printing a message and terminating the program. /// /// See [`sus_check_with_message`]($sus_check_with_message) to add a /// message to the display of the panic. /// /// The displayed output can be controlled by overriding the behaviour of -/// [`sus_panic`]($sus_panic) as described there. +/// [`sus::panic`]($sus::panic) as described there. #define sus_check(...) \ if (![](bool x) { return x; }(__VA_ARGS__)) [[unlikely]] { \ - sus_panic(); \ + ::sus::panic(); \ } \ static_assert(true) /// Verifies that the input `cond`, evaluated to a `bool`, is true. Otherwise, -/// it will [`panic`]($sus_panic), printing a customized message, and +/// it will [`panic`]($sus::panic), printing a customized message, and /// terminating the program. /// /// Use [`sus_check`]($sus_check) when there's nothing useful to add /// in the message. /// /// The displayed output can be controlled by overriding the behaviour of -/// [`sus_panic`]($sus_panic) as described there. If the +/// [`sus::panic`]($sus::panic) as described there. If the /// `SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER` macro does not consume the `msg`, /// this macro will avoid instantiating it at all. #define sus_check_with_message(cond, msg) \ if (!(cond)) [[unlikely]] { \ - sus_panic_with_message(msg); \ + ::sus::panic(msg); \ } \ static_assert(true) diff --git a/sus/assertions/debug_check.h b/sus/assertions/debug_check.h index 411fbc0ce..f0353fcc1 100644 --- a/sus/assertions/debug_check.h +++ b/sus/assertions/debug_check.h @@ -18,7 +18,7 @@ #include "sus/macros/assume.h" #include "sus/macros/compiler.h" -/// Check a condition in debug builds, causing a `sus_panic()` if the condition +/// Check a condition in debug builds, causing a `sus::panic()` if the condition /// fails. Nothing is checked in release builds. /// /// The condition must not have side effects, and should not call any functions diff --git a/sus/assertions/panic.cc b/sus/assertions/panic.cc index b8dde7c95..79ec4e7db 100644 --- a/sus/assertions/panic.cc +++ b/sus/assertions/panic.cc @@ -20,24 +20,22 @@ namespace sus::assertions::__private { -// Defined outside the header to avoid fprintf in the header. -void print_panic_message(const char* msg, - const PanicLocation& location) noexcept { - fprintf(stderr, "PANIC! at '%s', %s:%u:%u\n", msg, location.file_name, - location.line, location.column); +static void print_panic_location(const PanicLocation& location) noexcept { + fprintf(stderr, "PANIC! at %s:%u:%u\n", location.file_name, location.line, + location.column); } +// Defined outside the header to avoid fprintf in the header. void print_panic_message(std::string_view msg, const PanicLocation& location) noexcept { - fprintf(stderr, "PANIC! at '"); - for (char c : msg) fprintf(stderr, "%c", c); - fprintf(stderr, "', %s:%u:%u\n", location.file_name, location.line, - location.column); -} - -void print_panic_location(const PanicLocation& location) noexcept { - fprintf(stderr, "PANIC! at %s:%u:%u\n", location.file_name, location.line, - location.column); + if (msg.empty()) { + print_panic_location(location); + } else { + fprintf(stderr, "PANIC! at '"); + for (char c : msg) fprintf(stderr, "%c", c); + fprintf(stderr, "', %s:%u:%u\n", location.file_name, location.line, + location.column); + } } } // namespace sus::assertions::__private diff --git a/sus/assertions/panic.h b/sus/assertions/panic.h index 79e59636a..325fdc72b 100644 --- a/sus/assertions/panic.h +++ b/sus/assertions/panic.h @@ -24,8 +24,8 @@ namespace sus { /// Checking for (e.g. [`sus_check`]($sus_check)) and handling -/// (e.g. [`sus_panic`]($sus_panic), -/// [`sus_unreachable`]($sus_unreachable)) unexpected runtime +/// (e.g. [`sus::panic`]($sus::panic), +/// [`sus::unreachable`]($sus::unreachable)) unexpected runtime /// conditions. namespace assertions {} } // namespace sus @@ -56,81 +56,66 @@ struct PanicLocation { }; namespace __private { -void print_panic_message(const char& msg, - const PanicLocation& location) noexcept; void print_panic_message(std::string_view msg, const PanicLocation& location) noexcept; -void print_panic_location(const PanicLocation& location) noexcept; } // namespace __private -} // namespace sus::assertions - -#if defined(SUS_PROVIDE_PRINT_PANIC_LOCATION_HANDLER) -# define _sus_panic_location_handler(loc) \ - SUS_PROVIDE_PRINT_PANIC_LOCATION_HANDLER(loc) -#else -# define _sus_panic_location_handler(loc) \ - ::sus::assertions::__private::print_panic_location(loc) -#endif - -#if defined(SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER) -# define _sus_panic_message_handler(msg, loc) \ - SUS_PROVIDE_PRINT_PANIC_LOCATION_HANDLER(msg, loc) -#else -# define _sus_panic_message_handler(msg, loc) \ - ::sus::assertions::__private::print_panic_message(msg, loc) -#endif - -#if defined(SUS_PROVIDE_PANIC_HANDLER) -# define _sus_panic_handler() SUS_PROVIDE_PANIC_HANDLER() -#elif __has_builtin(__builtin_trap) -# define _sus_panic_handler() __builtin_trap() -#else -# define _sus_panic_handler() std::abort() -#endif - -/// Terminate the program. +/// Terminate the program, after printing a message. /// /// The default behaviour of this function is to `__builtin_trap()` when /// possible and [`std::abort()`]( -/// https://en.cppreference.com/w/cpp/utility/program/abort) otherwise. -/// The behaviour of this function can be overridden by defining a -/// `SUS_PROVIDE_PANIC_HANDLER()` macro when compiling the library. +/// https://en.cppreference.com/w/cpp/utility/program/abort) otherwise. The +/// behaviour of this function can be overridden by defining a +/// `SUS_PROVIDE_PANIC_HANDLER()` macro when compiling. The panic +/// message will be printed to stderr before aborting. This behaviour can be +/// overridden by defining a `SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER()` macro +/// when compiling. Message handling can be suppressed entirely by +/// defining a `SUS_PANIC_ELIDE_MESSAGE` macro. This can be advantageous for +/// optimised builds, as it turns `panic` into just calling the panic handler. +/// `SUS_PROVIDE_PANIC_HANDLER`, `SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER`, and +/// `SUS_PANIC_ELIDE_MESSAGE` must all have a consistent definition when +/// building Subspace and any binaries that link against it. This means you can +/// change them for different build configurations, but cannot change them for +/// different targets within the same build configuration. If used as a shared +/// library, the compilation of calling code must match how the Subspace library was built. /// -/// The panic message will be printed to stderr before aborting. This behaviour -/// can be overridden by defining a `SUS_PROVIDE_PRINT_PANIC_LOCATION_HANDLER()` -/// macro when compiling. The same handler must be used as when building the -/// library itself. So if used as a shared library, it can not be modified by -/// the calling code. The `SUS_PROVIDE_PRINT_PANIC_LOCATION_HANDLER()` macro -/// receives a single argument which is a [`PanicLocation`]( -/// $sus::assertions::PanicLocation). +/// The `SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER()` macro receives two arguments: +/// * A message, which is a `const char*`, a `std::string_view` or a +/// `std::string`. Overloads should be used to handle each case. +/// * A [`PanicLocation`]($sus::assertions::PanicLocation). +/// If the `SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER` macro does not consume the +/// `msg`, this macro will avoid instantiating it at all. /// /// # Safety /// /// If `SUS_PROVIDE_PANIC_HANDLER()` is defined, the macro _must_ not return or /// Undefined Behaviour will result. -#define sus_panic() \ - _sus_panic_location_handler(::sus::assertions::PanicLocation::current()); \ - _sus_panic_handler(); \ - static_assert(true) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wattributes" +[[noreturn, gnu::always_inline, gnu::nodebug]] +inline void panic(std::string_view message = "", + PanicLocation loc = PanicLocation::current()) noexcept +{ +#if !defined(SUS_PANIC_ELIDE_MESSAGE) +# if defined(SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER) + SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER(message, loc); +# else + ::sus::assertions::__private::print_panic_message(message, loc); +# endif // SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER +#endif // SUS_PANIC_ELIDE_MESSAGE -/// Terminate the program, after printing a message. -/// -/// The default behaviour of this function is to abort(). The behaviour of this -/// function can be overridden by defining a `SUS_PROVIDE_PANIC_HANDLER()` macro -/// when compiling the library. -/// -/// The panic message will be printed to stderr before aborting. This behaviour -/// can be overridden by defining a `SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER()` -/// macro when compiling the library. The -/// `SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER()` macro receives two arguments: -/// * A message, which is a `const char*`, a `std::string_view` or a -/// `std::string`. Overloads should be used to handle each case. -/// * A [`PanicLocation`]($sus::assertions::PanicLocation). -/// If the `SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER` macro does not consume the -/// `msg`, this macro will avoid instantiating it at all. -#define sus_panic_with_message(msg) \ - _sus_panic_message_handler((msg), \ - ::sus::assertions::PanicLocation::current()); \ - _sus_panic_handler(); \ - static_assert(true) +#if defined(SUS_PROVIDE_PANIC_HANDLER) + SUS_PROVIDE_PANIC_HANDLER(); +#elif __has_builtin(__builtin_trap) + __builtin_trap(); +#else + std::abort(); +#endif // SUS_PROVIDE_PANIC_HANDLER +} +#pragma GCC diagnostic pop + +} // namespace sus::assertions + +namespace sus { + using ::sus::assertions::panic; +} diff --git a/sus/assertions/panic_unittest.cc b/sus/assertions/panic_unittest.cc index 837410e80..0647d0b4c 100644 --- a/sus/assertions/panic_unittest.cc +++ b/sus/assertions/panic_unittest.cc @@ -14,7 +14,9 @@ #include "sus/assertions/panic.h" +#include "fmt/format.h" #include "googletest/include/gtest/gtest.h" +#include "panic.h" // Incredibly, on Posix we can use [0-9] but on Windows we can't. Yet on Windows // we can use `\d` and on Posix we can't (or it doesn't match). @@ -24,32 +26,38 @@ # define DIGIT "[0-9]" #endif +// TODO: add cases for `SUS_PROVIDE_PANIC_HANDLER` and +// `SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER` when it's clear how to test them +// with modules. +#if defined(SUS_PANIC_ELIDE_MESSAGE) +# define EXPECTED_MESSAGE(message) "^$" +#else +# define EXPECTED_MESSAGE(message) "^PANIC! at " message ".*panic_unittest.cc:" DIGIT "+:" DIGIT "+\n$" +#endif + namespace sus { namespace { + TEST(PanicDeathTest, Panic) { #if GTEST_HAS_DEATH_TEST - EXPECT_DEATH(sus_panic(), - "^PANIC! at .*panic_unittest.cc:" DIGIT "+:" DIGIT "+\n$"); + EXPECT_DEATH(sus::panic(), + EXPECTED_MESSAGE("")); #endif } TEST(PanicDeathTest, WithMessage) { #if GTEST_HAS_DEATH_TEST - EXPECT_DEATH(sus_panic_with_message("hello world"), - "^PANIC! at 'hello world', .*panic_unittest.cc:" DIGIT "+:" DIGIT - "+\n$"); + EXPECT_DEATH(sus::panic("hello world"), EXPECTED_MESSAGE("'hello world', ")); #endif #if GTEST_HAS_DEATH_TEST - EXPECT_DEATH(sus_panic_with_message( + EXPECT_DEATH(sus::panic( std::string_view("hello world123").substr(0u, 11u)), - "^PANIC! at 'hello world', .*panic_unittest.cc:" DIGIT "+:" DIGIT - "+\n$"); + EXPECTED_MESSAGE("'hello world', ")); #endif #if GTEST_HAS_DEATH_TEST - EXPECT_DEATH(sus_panic_with_message(std::string("hello world")), - "^PANIC! at 'hello world', .*panic_unittest.cc:" DIGIT "+:" DIGIT - "+\n$"); + EXPECT_DEATH(sus::panic(std::string("hello world")), + EXPECTED_MESSAGE("'hello world', ")); #endif } diff --git a/sus/assertions/unreachable.h b/sus/assertions/unreachable.h index 2e9c16426..0af660f36 100644 --- a/sus/assertions/unreachable.h +++ b/sus/assertions/unreachable.h @@ -14,18 +14,16 @@ #pragma once +#include "panic.h" #include "sus/assertions/panic.h" #include "sus/macros/builtin.h" #include "sus/marker/unsafe.h" -#if __has_builtin(__builtin_unreachable) -# define _sus_unreachable_unchecked_impl() __builtin_unreachable() -#else -# define _sus_unreachable_unchecked_impl() __assume(false) -#endif - +namespace sus::assertions { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wattributes" /// Indicates to the developer that the location should not be reached, and -/// terminates the program with a [`panic`]($sus_panic). +/// terminates the program with a [`panic`]($sus::panic). /// /// This is similar to [`std::unreachable!`]( /// https://doc.rust-lang.org/stable/std/macro.unreachable.html) in Rust, @@ -36,12 +34,14 @@ /// https://en.cppreference.com/w/cpp/utility/unreachable) in C++ which is /// Undefined Behaviour if reached. It is closer to [`std::abort`]( /// https://en.cppreference.com/w/cpp/utility/program/abort) except built on -/// top of [`sus_panic`]($sus_panic). +/// top of [`sus::panic`]($sus::panic). /// The Subspace library matches the safer behaviour of Rust to avoid confusion /// and security bugs when working across languages. Use -/// [`sus_unreachable_unchecked`]($sus_unreachable_unchecked) to +/// [`sus::unreachable_unchecked`]($sus::unreachable_unchecked) to /// indicate to the compiler the code is not reachable. -#define sus_unreachable() sus_panic_with_message("entered unreachable code") +[[noreturn, gnu::always_inline, gnu::nodebug]] inline void unreachable(PanicLocation loc = PanicLocation::current()) { + [[clang::always_inline]] ::sus::panic("entered unreachable code", loc); +} /// Indicates to the compiler that the location will never be reached, allowing /// it to optimize code generation accordingly. If this function is actually @@ -52,7 +52,17 @@ /// /// # Safety /// This function must never actually be reached, or Undefined Behaviour occurs. -#define sus_unreachable_unchecked(unsafe_fn_marker) \ - static_assert(std::same_as); \ - _sus_unreachable_unchecked_impl() +[[noreturn, gnu::always_inline, gnu::nodebug]] inline void unreachable_unchecked(::sus::marker::UnsafeFnMarker) { +#if __has_builtin(__builtin_unreachable) + __builtin_unreachable(); +#else + __assume(false); +#endif +} +#pragma GCC diagnostic pop +} // namespace ::sus::assertions + +namespace sus { + using sus::assertions::unreachable; + using sus::assertions::unreachable_unchecked; +} diff --git a/sus/assertions/unreachable_unittest.cc b/sus/assertions/unreachable_unittest.cc index 0e2a5a0bb..169c04a2e 100644 --- a/sus/assertions/unreachable_unittest.cc +++ b/sus/assertions/unreachable_unittest.cc @@ -31,7 +31,7 @@ namespace { TEST(UnreachableDeathTest, Unreachable) { #if GTEST_HAS_DEATH_TEST - EXPECT_DEATH(sus_unreachable(), + EXPECT_DEATH(sus::unreachable(), "^PANIC! at .*unreachable_unittest.cc:" DIGIT "+:" DIGIT "+\n$"); #endif } @@ -42,7 +42,7 @@ TEST(Unreachable, Unchecked) { } // We can't actually land here or we'd introduce UB, but the test confirms // we can write it and it compiles without warnings. - sus_unreachable_unchecked(unsafe_fn); + sus::unreachable_unchecked(unsafe_fn); } } // namespace diff --git a/sus/boxed/box.h b/sus/boxed/box.h index 3109f5cc7..499120747 100644 --- a/sus/boxed/box.h +++ b/sus/boxed/box.h @@ -75,7 +75,7 @@ struct [[_sus_trivial_abi]] BoxBase /// https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique) /// but built into the type. /// A moved-from `Box` may not be used except to be assigned to or destroyed. -/// Using a moved-from `Box` will [`panic`]($sus_panic) and +/// Using a moved-from `Box` will [`panic`]($sus::panic) and /// terminate the program rather than operate on a null. This prevents /// Undefined Behaviour and memory bugs caused by dereferencing null or using /// null in unintended ways. diff --git a/sus/choice/choice_unittest.cc b/sus/choice/choice_unittest.cc index 9b37418ba..e7add2202 100644 --- a/sus/choice/choice_unittest.cc +++ b/sus/choice/choice_unittest.cc @@ -48,7 +48,7 @@ struct fmt::formatter { case Second: return fmt::format_to(ctx.out(), "Second"); case Third: return fmt::format_to(ctx.out(), "Third"); } - sus_unreachable(); + sus::unreachable(); } }; diff --git a/sus/collections/__private/slice_mut_methods.inc b/sus/collections/__private/slice_mut_methods.inc index 1d84a66d6..92536d52a 100644 --- a/sus/collections/__private/slice_mut_methods.inc +++ b/sus/collections/__private/slice_mut_methods.inc @@ -597,7 +597,7 @@ constexpr RSplitNMut rsplitn_mut(usize n, index < len(), "partition_at_index index greater than length of slice"); // TODO: Requires Iterator::enumerate(), max_by(), min_by() - sus_unreachable(); + ::sus::unreachable(); } /// Reorder the slice with a key extraction function such that the element at diff --git a/sus/collections/iterators/drain.h b/sus/collections/iterators/drain.h index 1542fae4d..ad48b760f 100644 --- a/sus/collections/iterators/drain.h +++ b/sus/collections/iterators/drain.h @@ -73,7 +73,7 @@ struct [[nodiscard]] Drain final /// /// Calling this function will always panic. constexpr Drain& operator=(Drain&&) noexcept { - sus_panic_with_message("attempt to assign to Drain iterator"); + ::sus::panic("attempt to assign to Drain iterator"); } ~Drain() noexcept { diff --git a/sus/env/var.h b/sus/env/var.h index fc6a9c87b..e56a72e70 100644 --- a/sus/env/var.h +++ b/sus/env/var.h @@ -84,6 +84,6 @@ struct sus::error::ErrorImpl<::sus::env::VarError> { case ::sus::env::VarError::InvalidKeyEncoding: return "InvalidKeyEncoding"; } - sus_unreachable(); + ::sus::unreachable(); } }; diff --git a/sus/error/error.h b/sus/error/error.h index dce97ba9b..8c8b77fa6 100644 --- a/sus/error/error.h +++ b/sus/error/error.h @@ -42,9 +42,9 @@ namespace sus { /// The following are the primary interfaces of the panic system and the /// responsibilities they cover: /// -/// * [`sus_panic`]($sus_panic) (Constructing, Propagating) -/// * [`SUS_PROVIDE_PRINT_PANIC_LOCATION_HANDLER`]($sus_panic) (Reporting) -/// * [`SUS_PROVIDE_PANIC_HANDLER`]($sus_panic) (Reacting) +/// * [`sus::panic`]($sus::panic) (Constructing, Propagating) +/// * [`SUS_PROVIDE_PRINT_PANIC_MESSAGE_HANDLER`]($sus::panic) (Reporting) +/// * [`SUS_PROVIDE_PANIC_HANDLER`]($sus::panic) (Reacting) /// /// The following are the primary interfaces of the error system and the /// responsibilities they cover: @@ -293,7 +293,7 @@ concept HasErrorSource = requires(const T& t) { /// switch (self) { /// case ErrorReason::SomeReason: return "we saw SomeReason happen"; /// } -/// sus_unreachable(); +/// sus::unreachable(); /// } /// }; /// diff --git a/sus/error/error_unittest.cc b/sus/error/error_unittest.cc index ead9f30e3..e943f1127 100644 --- a/sus/error/error_unittest.cc +++ b/sus/error/error_unittest.cc @@ -47,7 +47,7 @@ struct sus::error::ErrorImpl { switch (self) { case ErrorReason::SomeReason: return "we saw SomeReason happen"; } - sus_unreachable(); + sus::unreachable(); } }; static_assert(sus::error::error_display(ErrorReason::SomeReason) == diff --git a/sus/fn/fn.h b/sus/fn/fn.h index 51eb64826..bbfe9c76e 100644 --- a/sus/fn/fn.h +++ b/sus/fn/fn.h @@ -37,7 +37,7 @@ namespace sus { /// As these are concepts, not concrete types, they can not enforce any /// behaviour but rather represent a protocol of expectations. Types designed to /// satisfy these concepts should adhere to them, and safely handle misuse, such -/// as panicking (via [`panic`]($sus_panic)) if called twice when it is not +/// as panicking (via [`panic`]($sus::panic)) if called twice when it is not /// supported. /// /// To make a type satisfy [`Fn`]($sus::fn::Fn) it should have a diff --git a/sus/fn/fn_concepts.h b/sus/fn/fn_concepts.h index 68d5cfdad..aa82ced2e 100644 --- a/sus/fn/fn_concepts.h +++ b/sus/fn/fn_concepts.h @@ -81,10 +81,10 @@ struct Anything { /// called correctly. It is moved-from after calling, and it should only be /// called once. /// -/// Calling a `FnOnce` multiple times may [`panic`]($sus_panic) +/// Calling a `FnOnce` multiple times may [`panic`]($sus::panic) /// or cause Undefined Behaviour. /// Not moving the `FnOnce` when calling it may fail to compile, -/// [`panic`]($sus_panic), or cause Undefined Behaviour depending on the type +/// [`panic`]($sus::panic), or cause Undefined Behaviour depending on the type /// that is being used to satisfy `FnOnce`. /// /// # Type erasure diff --git a/sus/iter/generator.h b/sus/iter/generator.h index abc98159b..32aedfedc 100644 --- a/sus/iter/generator.h +++ b/sus/iter/generator.h @@ -105,7 +105,7 @@ class IterPromise { constexpr auto initial_suspend() noexcept { return std::suspend_always(); } constexpr auto final_suspend() noexcept { return std::suspend_always(); } - constexpr void unhandled_exception() noexcept { sus_unreachable(); } + constexpr void unhandled_exception() noexcept { ::sus::unreachable(); } constexpr Option take() & noexcept { return yielded_.take(); } diff --git a/sus/num/__private/intrinsics.h b/sus/num/__private/intrinsics.h index 0d1ed4ded..73d07f53c 100644 --- a/sus/num/__private/intrinsics.h +++ b/sus/num/__private/intrinsics.h @@ -1768,7 +1768,7 @@ __sus_pure_const constexpr inline ::sus::num::FpCategory float_category( case norm: return ::sus::num::FpCategory::Normal; case subnorm: return ::sus::num::FpCategory::Subnormal; case zero: return ::sus::num::FpCategory::Zero; - default: sus_unreachable_unchecked(::sus::marker::unsafe_fn); + default: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } #else @@ -1790,7 +1790,7 @@ __sus_pure_const constexpr inline ::sus::num::FpCategory float_category( case FP_NORMAL: return ::sus::num::FpCategory::Normal; case FP_SUBNORMAL: return ::sus::num::FpCategory::Subnormal; case FP_ZERO: return ::sus::num::FpCategory::Zero; - default: sus_unreachable_unchecked(::sus::marker::unsafe_fn); + default: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } } diff --git a/sus/num/try_from_int_error_impl.h b/sus/num/try_from_int_error_impl.h index 092aed851..f71ed99cf 100644 --- a/sus/num/try_from_int_error_impl.h +++ b/sus/num/try_from_int_error_impl.h @@ -53,7 +53,7 @@ struct sus::error::ErrorImpl { switch (e.kind()) { case sus::num::TryFromIntError::Kind::OutOfBounds: return "out of bounds"; } - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } }; diff --git a/sus/num/types.h b/sus/num/types.h index 3928916b8..50d708f2a 100644 --- a/sus/num/types.h +++ b/sus/num/types.h @@ -40,7 +40,7 @@ namespace sus { /// types, but are safer than primitive C++ types and eliminate many classes of /// bugs that often lead to security vulnerabilities: /// * Integer overflow is not allowed by default (see [Overflow behaviour]( -/// #overflow-behaviour)), and will [`panic`]($sus_panic) to terminate the +/// #overflow-behaviour)), and will [`panic`]($sus::panic) to terminate the /// program. /// Intentional overflow can be achieved through methods like /// [`wrapping_add`]($sus::num::i32::wrapping_add) or diff --git a/sus/option/option.h b/sus/option/option.h index d60201395..1ffd5c0bb 100644 --- a/sus/option/option.h +++ b/sus/option/option.h @@ -365,7 +365,7 @@ namespace sus { /// another [`Option`]($sus::option::Option) as input, and produce an /// [`Option`]($sus::option::Option) as output. /// Only the [`and_that`]($sus::option::Option::and_that) -/// method can produce an [`Option`]($sus::option::Option) value having a +/// method can produce an [`Option`]($sus::option::Option) value having a /// different inner type `U` than [`Option`]($sus::option::Option). /// /// | method | self | input | output | @@ -853,7 +853,7 @@ class Option final { // Result::unwrap_unchecked benefits from telling the compiler explicitly // that the other states are never set. Match that here until shown it's // actually not useful. - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } constexpr inline T unwrap_unchecked( @@ -1724,7 +1724,7 @@ class Option final { r.as_value_unchecked(::sus::marker::unsafe_fn)); case None: return r.is_none(); } - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template requires(::sus::cmp::Eq) @@ -1736,7 +1736,7 @@ class Option final { r.as_value_unchecked(::sus::marker::unsafe_fn)); case None: return r.is_none(); } - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template @@ -1776,7 +1776,7 @@ class Option final { else return std::strong_ordering::equivalent; } - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template requires(::sus::cmp::ExclusiveStrongOrd) @@ -1796,7 +1796,7 @@ class Option final { else return std::strong_ordering::equivalent; } - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } // sus::cmp::Ord> trait. @@ -1818,7 +1818,7 @@ class Option final { else return std::weak_ordering::equivalent; } - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template requires(::sus::cmp::ExclusiveOrd) @@ -1838,7 +1838,7 @@ class Option final { else return std::weak_ordering::equivalent; } - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } // sus::cmp::PartialOrd> trait. @@ -1860,7 +1860,7 @@ class Option final { else return std::partial_ordering::equivalent; } - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } friend constexpr inline std::partial_ordering operator<=>( const Option& l, const Option& r) noexcept @@ -1880,7 +1880,7 @@ class Option final { else return std::partial_ordering::equivalent; } - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template diff --git a/sus/result/__private/storage.h b/sus/result/__private/storage.h index 5884a0c39..e8a558ef1 100644 --- a/sus/result/__private/storage.h +++ b/sus/result/__private/storage.h @@ -138,7 +138,7 @@ struct StorageVoid { switch (o.state) { case Ok: break; case Err: std::construct_at(&u.err, o.u.err); break; - case Moved: sus_panic_with_message("Result used after move"); + case Moved: ::sus::panic("Result used after move"); } // After construct_at since it may write into the field if it's in tail // padding. @@ -171,7 +171,7 @@ struct StorageVoid { switch (o.state) { case Ok: break; case Err: std::construct_at(&u.err, o.u.err); break; - case Moved: sus_unreachable_unchecked(::sus::marker::unsafe_fn); + case Moved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } // After construct_at since it may write into the field if it's in tail @@ -189,7 +189,7 @@ struct StorageVoid { switch (o.state) { case Ok: break; case Err: std::construct_at(&u.err, ::sus::move(o.u.err)); break; - case Moved: sus_panic_with_message("Result used after move"); + case Moved: ::sus::panic("Result used after move"); } // After construct_at since it may write into the field if it's in tail // padding. @@ -224,7 +224,7 @@ struct StorageVoid { std::construct_at(&u.err, ::sus::move(o.u.err)); std::destroy_at(&o.u.err); break; - case Moved: sus_unreachable_unchecked(::sus::marker::unsafe_fn); + case Moved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } // After construct_at since it may write into the field if it's in tail @@ -384,7 +384,7 @@ struct StorageNonVoid { switch (o.state) { case Ok: std::construct_at(&u.ok, o.u.ok); break; case Err: std::construct_at(&u.err, o.u.err); break; - case Moved: sus_panic_with_message("Result used after move"); + case Moved: ::sus::panic("Result used after move"); } // After construct_at since it may write into the field if it's in tail // padding. @@ -419,7 +419,7 @@ struct StorageNonVoid { switch (o.state) { case Ok: std::construct_at(&u.ok, o.u.ok); break; case Err: std::construct_at(&u.err, o.u.err); break; - case Moved: sus_unreachable_unchecked(::sus::marker::unsafe_fn); + case Moved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } // After construct_at since it may write into the field if it's in tail @@ -441,7 +441,7 @@ struct StorageNonVoid { switch (o.state) { case Ok: std::construct_at(&u.ok, ::sus::move(o.u.ok)); break; case Err: std::construct_at(&u.err, ::sus::move(o.u.err)); break; - case Moved: sus_panic_with_message("Result used after move"); + case Moved: ::sus::panic("Result used after move"); } // After construct_at since it may write into the field if it's in tail // padding. @@ -482,7 +482,7 @@ struct StorageNonVoid { std::construct_at(&u.err, ::sus::move(o.u.err)); std::destroy_at(&o.u.err); break; - case Moved: sus_unreachable_unchecked(::sus::marker::unsafe_fn); + case Moved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } // After construct_at since it may write into the field if it's in tail diff --git a/sus/result/result.h b/sus/result/result.h index f120937b5..db52c163c 100644 --- a/sus/result/result.h +++ b/sus/result/result.h @@ -241,7 +241,7 @@ class [[nodiscard]] Result final { } else if (storage_.is_err()) { return Result(WITH_ERR, ::sus::clone(storage_.get_err())); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } @@ -251,7 +251,7 @@ class [[nodiscard]] Result final { !(::sus::mem::CopyOrRefOrVoid && ::sus::mem::Copy)) { if (source.storage_.is_moved()) [[unlikely]] { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } else if (&source == this) [[unlikely]] { // Nothing to do. } else if (storage_.is_moved()) { @@ -429,7 +429,7 @@ class [[nodiscard]] Result final { } else if (storage_.is_err()) { return sus::fn::ReturnOnce::with_err(storage_.take_err()); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } template <::sus::fn::FnOnce<::sus::fn::NonVoid()> AndFn> @@ -444,7 +444,7 @@ class [[nodiscard]] Result final { } else if (storage_.is_err()) { return sus::fn::ReturnOnce::with_err(storage_.take_err()); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } /// Converts from `Result` to [`Option`]($sus::option::Option). @@ -463,7 +463,7 @@ class [[nodiscard]] Result final { storage_.drop_err(); return Option(); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } @@ -478,7 +478,7 @@ class [[nodiscard]] Result final { } else if (storage_.is_err()) { return Option(storage_.take_err()); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } @@ -493,12 +493,12 @@ class [[nodiscard]] Result final { return storage_.template get_ok(); } else if (storage_.is_err()) { if constexpr (fmt::is_formattable::value) { - sus_panic_with_message(fmt::to_string(storage_.get_err())); + ::sus::panic(fmt::to_string(storage_.get_err())); } else { - sus_panic_with_message("Result has error state"); + ::sus::panic("Result has error state"); } } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } constexpr const std::remove_reference_t& as_value() && = delete; @@ -514,12 +514,12 @@ class [[nodiscard]] Result final { return storage_.template get_ok_mut(); } else if (storage_.is_err()) { if constexpr (fmt::is_formattable::value) { - sus_panic_with_message(fmt::to_string(storage_.get_err())); + ::sus::panic(fmt::to_string(storage_.get_err())); } else { - sus_panic_with_message("Result has error state"); + ::sus::panic("Result has error state"); } } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } /// Returns a const reference to the contained `Err` value. @@ -531,14 +531,14 @@ class [[nodiscard]] Result final { return storage_.get_err(); } else if (storage_.is_ok()) { if constexpr (std::is_void_v) { - sus_panic_with_message("Result has ok state"); + ::sus::panic("Result has ok state"); } else if constexpr (!fmt::is_formattable::value) { - sus_panic_with_message("Result has ok state"); + ::sus::panic("Result has ok state"); } else { - sus_panic_with_message(fmt::to_string(storage_.template get_ok())); + ::sus::panic(fmt::to_string(storage_.template get_ok())); } } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } constexpr const E& as_err() && = delete; @@ -557,12 +557,12 @@ class [[nodiscard]] Result final { return storage_.template take_ok(); } else if (storage_.is_err()) { if constexpr (fmt::is_formattable::value) { - sus_panic_with_message(fmt::to_string(storage_.get_err())); + ::sus::panic(fmt::to_string(storage_.get_err())); } else { - sus_panic_with_message("Result has error state"); + ::sus::panic("Result has error state"); } } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } @@ -580,12 +580,12 @@ class [[nodiscard]] Result final { return storage_.template take_ok(); } else if (storage_.is_err()) { if constexpr (fmt::is_formattable::value) { - sus_panic_with_message(fmt::format("{}: {}", msg, storage_.get_err())); + ::sus::panic(fmt::format("{}: {}", msg, storage_.get_err())); } else { - sus_panic_with_message(msg); + ::sus::panic(msg); } } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } @@ -606,7 +606,7 @@ class [[nodiscard]] Result final { else return; } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } @@ -624,7 +624,7 @@ class [[nodiscard]] Result final { // construction, possibly because the `state_` gets clobbered below? // The signed code version at https://godbolt.org/z/Gax47shsb improves // greatly when the compiler is informed about the UB here. - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } return storage_.template take_ok(); } @@ -638,14 +638,14 @@ class [[nodiscard]] Result final { return storage_.take_err(); } else if (storage_.is_ok()) { if constexpr (std::is_void_v) { - sus_panic_with_message("Result has ok state"); + ::sus::panic("Result has ok state"); } else if constexpr (!fmt::is_formattable::value) { - sus_panic_with_message("Result has ok state"); + ::sus::panic("Result has ok state"); } else { - sus_panic_with_message(fmt::to_string(storage_.template get_ok())); + ::sus::panic(fmt::to_string(storage_.template get_ok())); } } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } @@ -660,7 +660,7 @@ class [[nodiscard]] Result final { if (!storage_.is_err()) { // Match the code in unwrap_unchecked, and tell the compiler that the // `state_` is an Err before clobbering it. - sus_unreachable_unchecked(::sus::marker::unsafe_fn); + ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } return storage_.take_err(); } @@ -683,7 +683,7 @@ class [[nodiscard]] Result final { } else if (storage_.is_err()) { return ::sus::fn::call_once(::sus::move(op), storage_.take_err()); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } @@ -700,7 +700,7 @@ class [[nodiscard]] Result final { return ::sus::option::OptionIter&>( Option&>()); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } constexpr ::sus::option::OptionIter< @@ -717,7 +717,7 @@ class [[nodiscard]] Result final { return ::sus::option::OptionIter&>( Option&>()); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } @@ -730,7 +730,7 @@ class [[nodiscard]] Result final { } else if (storage_.is_err()) { return ::sus::option::OptionIter(Option()); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } constexpr ::sus::option::OptionIter iter_mut() && noexcept @@ -744,7 +744,7 @@ class [[nodiscard]] Result final { storage_.drop_err(); return ::sus::option::OptionIter(Option()); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } } @@ -758,7 +758,7 @@ class [[nodiscard]] Result final { storage_.drop_err(); return ::sus::option::OptionIter(Option()); } else { - sus_panic_with_message("Result used after move"); + ::sus::panic("Result used after move"); } }