Skip to content

Removal of import std#19

Open
OldDev78 wants to merge 4 commits intoRedot-Engine:masterfrom
OldDev78:no-more-import-std
Open

Removal of import std#19
OldDev78 wants to merge 4 commits intoRedot-Engine:masterfrom
OldDev78:no-more-import-std

Conversation

@OldDev78
Copy link
Copy Markdown
Contributor

@OldDev78 OldDev78 commented May 7, 2026

Remove import std; and use STL headers in global module fragment instead.

Summary by CodeRabbit

  • Chores
    • Updated build/configuration to modernize compiler and module handling.
    • Adjusted third‑party build to use static linkage for the graphics library.
  • Tests
    • Migrated unit tests to doctest for clearer execution and reporting.
  • Improvements
    • Refactored math/core modules: added precise constants, minor API relaxations, and internal performance tweaks (no public API changes).

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 7, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6c3ce2f7-2dd1-4364-ae8f-7dc0f07254a9

📥 Commits

Reviewing files that changed from the base of the PR and between d0e39e1 and 334b879.

📒 Files selected for processing (1)
  • engine/native/core/CMakeLists.txt
✅ Files skipped from review due to trivial changes (1)
  • engine/native/core/CMakeLists.txt

📝 Walkthrough

Walkthrough

This PR converts module units to global module fragments with explicit standard headers, migrates unit tests from Boost.UT to doctest, updates math constants and some math implementations, and adjusts CMake presets, compiler flags, and third-party/static BGFX build settings.

Changes

C++ Module Refactoring & Test Framework Migration

Layer / File(s) Summary
Build Configuration & CMake Flags
CMakeLists.txt, CMakePresets.json, cmake/Compiler.cmake, engine/native/CMakeLists.txt
Remove experimental C++ import/module flags and Clang -stdlib=libc++; add explicit C standard and CMAKE_CXX_SCAN_FOR_MODULES; mark native thirdparty as SYSTEM.
CMake Test Configuration
cmake/Modules.cmake
Add DOCTEST_INCLUDE_DIR, remove Boost.UT bootstrap, add doctest includes to test targets, and link tests only to ${LIB_TARGET}.
Third-party Configuration
engine/native/thirdparty/CMakeLists.txt
Set BGFX_LIBRARY_TYPE to "STATIC" and enforce static-library build via cache variables.
Core Module Fragments
engine/native/core/definitions/definitions.cppm, engine/native/core/definitions/version.cppm, engine/native/core/math/math.cppm, engine/native/core/math/vector4.cppm
Convert module units to global module fragment (module;) with explicit standard headers and remove import std;.
Definitions
engine/native/core/definitions/definitions.cppm
Remove exported MAX_RECURSION constant.
Math Constants
engine/native/core/math/constants.cppm
Use std::numbers constants (e.g., SQRT13 = std::numbers::inv_sqrt3_v<double>) and add UINT32_MAX_D / UINT32_MAX_F.
Math Implementation
engine/native/core/math/math.cppm
Switch is_inf/is_finite to compiler builtins and use module-local PI for angle conversions.
Vector Implementation
engine/native/core/math/vector4.cppm
Add <cmath> include; comment out standard_layout static_assert; implementation unchanged otherwise.
Tests / Test Implementation
engine/native/core/math/math.test.cpp
Migrate tests from Boost.UT suite/expect to doctest TEST_CASE/REQUIRE; update constant references to module constants.
Core Target Properties
engine/native/core/CMakeLists.txt
Enable POSITION_INDEPENDENT_CODE for the definitions module library target.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Redot-Engine/DraconicEngine#12: Modifies third-party/bgfx integration and CMake submodule handling, related to these third-party and engine/native CMake changes.

Suggested reviewers

  • mcdubhghlas
  • Arctis-Fireblight

Poem

A rabbit hops through modules bright,
From import std to headers light,
Tests now skip Boost and run with glee,
CMake trimmed, constants tidy as can be —
A tiny hop, a cleaner tree. 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Removal of import std' directly and concisely describes the main objective of the pull request, which is to remove import std; statements and replace them with explicit STL headers in global module fragments.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@OldDev78 OldDev78 marked this pull request as ready for review May 8, 2026 23:35
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
engine/native/core/math/constants.cppm (1)

28-29: ⚡ Quick win

UINT32_MAX_D/UINT32_MAX_F are reciprocals, not max values — rename to avoid confusion.

Both constants hold 1.0 / std::numeric_limits<uint32_t>::max() ≈ 2.33×10⁻¹⁰. The name UINT32_MAX_D is a homonym for the C macro UINT32_MAX (4294967295), so any caller reading the name without checking the definition may silently use it as if it holds the max value instead of its reciprocal.

♻️ Suggested rename
-    constexpr double UINT32_MAX_D = 1. / std::numeric_limits<uint32_t>::max();
-    constexpr float  UINT32_MAX_F = 1.f / std::numeric_limits<uint32_t>::max();
+    constexpr double INV_UINT32_MAX_D = 1. / std::numeric_limits<uint32_t>::max();
+    constexpr float  INV_UINT32_MAX_F = 1.f / std::numeric_limits<uint32_t>::max();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@engine/native/core/math/constants.cppm` around lines 28 - 29, The constants
UINT32_MAX_D and UINT32_MAX_F are actually the reciprocal of the uint32 max (1.0
/ max) and should be renamed to avoid confusion; rename them to a clearer
identifier such as UINT32_INV_MAX_D and UINT32_INV_MAX_F (or
UINT32_RECIPROCAL_MAX_D/F) in constants.cppm and update every usage site to the
new names (search for UINT32_MAX_D and UINT32_MAX_F), keeping the same types and
values and updating any comments/docstrings to match the new meaning so callers
no longer mistake them for the maximum value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@engine/native/core/definitions/definitions.cppm`:
- Around line 1-3: The code uses std::is_arithmetic_v, std::is_trivial_v and
std::false_type but only includes <concepts>; add the missing <type_traits>
include at the top of the module unit so these type-trait identifiers are
declared (i.e., add the `#include` for <type_traits> alongside the existing
includes in the module preamble to ensure std::is_arithmetic_v,
std::is_trivial_v and std::false_type are available).

In `@engine/native/core/math/math.test.cpp`:
- Around line 7-9: The test calls draco::math::pow(2., .5) and compares it with
draco::math::SQRT2 using REQUIRE(result == expected), which can fail due to pow
not being correctly rounded; change the test to compute the left-hand side with
std::sqrt(2.0) (or draco::math::sqrt if you provide a correctly-rounded wrapper)
instead of draco::math::pow, or keep pow but replace the exact equality check
with a tolerance check (e.g., use Catch's Approx) comparing result to
std::numbers::sqrt2_v<double> or draco::math::SQRT2 to avoid 1-ULP spurious
failures.

In `@engine/native/core/math/vector4.cppm`:
- Line 99: The commented-out static_assert removed the only compile-time
guarantee that Vector4 is standard-layout, leaving the non-consteval operator[]
(which uses (&x)[i]) undefined behavior if the type changes; restore the
static_assert for std::is_standard_layout_v<Vector4> to re-establish the
invariant, or alternatively change the non-consteval operator[] implementation
in Vector4 to mirror the consteval path by using explicit member selection (x,
y, z, w) or a switch/array of pointers to members instead of (&x)[i], and add a
brief comment documenting the chosen approach.

---

Nitpick comments:
In `@engine/native/core/math/constants.cppm`:
- Around line 28-29: The constants UINT32_MAX_D and UINT32_MAX_F are actually
the reciprocal of the uint32 max (1.0 / max) and should be renamed to avoid
confusion; rename them to a clearer identifier such as UINT32_INV_MAX_D and
UINT32_INV_MAX_F (or UINT32_RECIPROCAL_MAX_D/F) in constants.cppm and update
every usage site to the new names (search for UINT32_MAX_D and UINT32_MAX_F),
keeping the same types and values and updating any comments/docstrings to match
the new meaning so callers no longer mistake them for the maximum value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8561d66f-d6f4-4132-b860-0a29c6e7afb5

📥 Commits

Reviewing files that changed from the base of the PR and between 17595c0 and d0e39e1.

📒 Files selected for processing (13)
  • CMakeLists.txt
  • CMakePresets.json
  • cmake/Compiler.cmake
  • cmake/Modules.cmake
  • engine/native/CMakeLists.txt
  • engine/native/core/definitions/definitions.cppm
  • engine/native/core/definitions/version.cppm
  • engine/native/core/math/constants.cppm
  • engine/native/core/math/math.cppm
  • engine/native/core/math/math.test.cpp
  • engine/native/core/math/vector4.cppm
  • engine/native/thirdparty/CMakeLists.txt
  • engine/native/thirdparty/doctest/doctest.h
💤 Files with no reviewable changes (2)
  • CMakeLists.txt
  • cmake/Compiler.cmake

Comment on lines +1 to +3
module;

#include <concepts>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does the C++23 standard require <concepts> to transitively include <type_traits>? Where are std::is_arithmetic_v, std::is_trivial_v, and std::false_type declared?

💡 Result:

No, the C++23 standard does not require <concepts> to transitively include <type_traits>. The header synopsis for <concepts> in the standard draft ([1][2]) defines concepts like same_as, derived_from, integral, etc., but does not include or require declarations from <type_traits> such as type traits or integral_constant (from which false_type derives). Header inclusions are not mandated by the standard beyond the synopsis; implementations may choose transitive includes for convenience, but it is not required.[3][1][2][4] std::is_arithmetic_v, std::is_trivial_v are declared in <type_traits> ([5][6][7][8]). std::false_type is declared in <type_traits> as it inherits from std::integral_constant<bool, false>, which is part of the metaprogramming types in that header ([6][9][10]).

Citations:


Add missing <type_traits> header — type-trait identifiers used without declaration.

This module uses std::is_arithmetic_v (line 13), std::is_trivial_v (line 16), and std::false_type (line 22), all declared in <type_traits> according to the C++ standard. The <concepts> header does not declare these identifiers, and the standard does not require <concepts> to transitively include <type_traits>. While some implementations include it transitively for convenience, relying on this is fragile and will fail on stricter implementations like MSVC STL. Since the PR goal is to replace import std; with precise STL headers, this include must be added.

🔧 Proposed fix
 module;

 `#include` <concepts>
+#include <type_traits>

 export module core.defs;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
module;
#include <concepts>
module;
`#include` <concepts>
`#include` <type_traits>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@engine/native/core/definitions/definitions.cppm` around lines 1 - 3, The code
uses std::is_arithmetic_v, std::is_trivial_v and std::false_type but only
includes <concepts>; add the missing <type_traits> include at the top of the
module unit so these type-trait identifiers are declared (i.e., add the `#include`
for <type_traits> alongside the existing includes in the module preamble to
ensure std::is_arithmetic_v, std::is_trivial_v and std::false_type are
available).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's a transitive include.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OldDev78, understood — on GCC (libstdc++) and Clang (libc++), <concepts> does pull in <type_traits> transitively in practice. Since the project exclusively targets GCC/Clang (as seen in cmake/Compiler.cmake), this holds. Just worth noting it won't work on MSVC STL, but given the targeted toolchain that's a valid conscious decision.

🐇 curious nibble


🧠 Learnings used
Learnt from: mcdubhghlas
Repo: Redot-Engine/DraconicEngine PR: 1
File: core/math/vector4.cppm:136-140
Timestamp: 2026-03-17T14:51:36.674Z
Learning: For all C++ module files (.cppm), ensure the build flags cover AVX2/-mfma unconditionally (as in the project: -mavx2 -mfma). If you use BMI1/BMI2 intrinsics in a module, also enable them explicitly with -mbmi and -mbmi2, since BMI features are not guaranteed by AVX2 alone. Note that SSE3 and older SSEs are guaranteed via ISA backwards compatibility on AVX2 targets, so no SSE2/SSE3 fallbacks are needed.

Comment on lines +7 to +9
double result = draco::math::pow(2., .5);
constexpr double expected = draco::math::SQRT2;
REQUIRE(result == expected);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

REQUIRE(result == expected) may be unreliable — std::pow(2., 0.5) is not guaranteed to match sqrt2_v<double> exactly.

std::numbers::sqrt2_v<double> is the correctly-rounded IEEE 754 double approximation of √2. std::pow(2., 0.5) goes through the general pow implementation, which — unlike sqrt — is not required by IEEE 754 or the C++ standard to be correctly rounded. On some libm implementations, pow(2., 0.5) may return a value that is 1 ULP off from sqrt2_v<double>, causing this test to fail spuriously.

Use std::sqrt(2.) (which is correctly rounded) or a tolerance-based check:

🐛 Proposed fix
 TEST_CASE("pow") {
-    double result = draco::math::pow(2., .5);
-    constexpr double expected = draco::math::SQRT2;
-    REQUIRE(result == expected);
+    double result = draco::math::pow(2., .5);
+    constexpr double expected = draco::math::SQRT2;
+    // pow is not required to be correctly-rounded; allow 1 ULP of slack
+    REQUIRE(result == doctest::Approx(expected).epsilon(1e-15));
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
double result = draco::math::pow(2., .5);
constexpr double expected = draco::math::SQRT2;
REQUIRE(result == expected);
double result = draco::math::pow(2., .5);
constexpr double expected = draco::math::SQRT2;
// pow is not required to be correctly-rounded; allow 1 ULP of slack
REQUIRE(result == doctest::Approx(expected).epsilon(1e-15));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@engine/native/core/math/math.test.cpp` around lines 7 - 9, The test calls
draco::math::pow(2., .5) and compares it with draco::math::SQRT2 using
REQUIRE(result == expected), which can fail due to pow not being correctly
rounded; change the test to compute the left-hand side with std::sqrt(2.0) (or
draco::math::sqrt if you provide a correctly-rounded wrapper) instead of
draco::math::pow, or keep pow but replace the exact equality check with a
tolerance check (e.g., use Catch's Approx) comparing result to
std::numbers::sqrt2_v<double> or draco::math::SQRT2 to avoid 1-ULP spurious
failures.

static_assert(alignof(Vector4) == 16, "Vector4 must be 16-byte aligned");
static_assert(trivial<Vector4>, "Vector4 must be trivial");
static_assert(std::is_standard_layout_v<Vector4>, "Vector4 must be standard layout");
//static_assert(std::is_standard_layout_v<Vector4>, "Vector4 must be standard layout");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if there is any other explanation or recent changes around the standard_layout assert
rg -n "standard_layout" --type cpp -C3
rg -n "is_standard_layout" --type cpp -C3

Repository: Redot-Engine/DraconicEngine

Length of output: 53


🏁 Script executed:

# First, locate the file
find . -name "vector4.cppm" -type f

Repository: Redot-Engine/DraconicEngine

Length of output: 110


🏁 Script executed:

# Read the file to check line 99 and surrounding context
# Get file info first
wc -l engine/native/core/math/vector4.cppm

Repository: Redot-Engine/DraconicEngine

Length of output: 112


🏁 Script executed:

# Read the full file to understand structure
cat -n engine/native/core/math/vector4.cppm | head -150

Repository: Redot-Engine/DraconicEngine

Length of output: 5729


🏁 Script executed:

# Search for the static_assert and operator[] in the cppm file
rg "static_assert|is_standard_layout|operator\[\]" engine/native/core/math/vector4.cppm -n -C 3

Repository: Redot-Engine/DraconicEngine

Length of output: 1078


Commented-out is_standard_layout assert removes the only guard for (&x)[i] pointer arithmetic.

The non-consteval branch of operator[] (lines 36, 48) uses (&x)[i] to index struct members, which is only well-defined if the type is standard layout. The static_assert at line 99 was the sole compile-time guarantee for this invariant, and removing it without explanation leaves the runtime path vulnerable to UB if the struct property ever changes.

Either restore the assert and address any failure, or add a comment explaining why it was removed and replace (&x)[i] with explicit member selection (as in the consteval path).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@engine/native/core/math/vector4.cppm` at line 99, The commented-out
static_assert removed the only compile-time guarantee that Vector4 is
standard-layout, leaving the non-consteval operator[] (which uses (&x)[i])
undefined behavior if the type changes; restore the static_assert for
std::is_standard_layout_v<Vector4> to re-establish the invariant, or
alternatively change the non-consteval operator[] implementation in Vector4 to
mirror the consteval path by using explicit member selection (x, y, z, w) or a
switch/array of pointers to members instead of (&x)[i], and add a brief comment
documenting the chosen approach.

JoltedJon
JoltedJon previously approved these changes May 8, 2026
Copy link
Copy Markdown
Contributor

@JoltedJon JoltedJon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a code review standpoint looks good to me. Not at computer so can't compile it right now

@OldDev78
Copy link
Copy Markdown
Contributor Author

OldDev78 commented May 9, 2026

From a code review standpoint looks good to me. Not at computer so can't compile it right now

Please test with different clang versions (>18) if possible.

Next, I'll specify clang as the compiler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants