From 23b9cafda817a75980bd1b24d19838e74cfa22d7 Mon Sep 17 00:00:00 2001 From: Dmytro Starosud Date: Wed, 15 Jul 2026 21:33:16 +0300 Subject: [PATCH] Fix deferred init narrowing #1446 by keeping brace-init in caller context. Use construct_from(lambda) so constexpr initializers are not lost across a call boundary, matching immediate initialization behavior. Add regression tests for literals (negative too), constexpr, aggregates. Update snapshots affected by the change. --- include/cpp2util.h | 33 ++++++ ...or-deferred-init-narrowing-aggregates.cpp2 | 52 +++++++++ ...for-deferred-init-narrowing-constexpr.cpp2 | 31 +++++ ...-for-deferred-init-narrowing-literals.cpp2 | 27 +++++ ...-deferred-init-narrowing-matrix-error.cpp2 | 54 +++++++++ ...rred-init-narrowing-negative-literals.cpp2 | 15 +++ ...red-init-narrowing-matrix-error.cpp.output | 57 +++++++++ .../mixed-lifetime-safety-pointer-init-4.cpp | 4 +- .../test-results/mixed-autodiff-taylor.cpp | 36 +++--- ...for-deferred-init-narrowing-aggregates.cpp | 75 ++++++++++++ ...rred-init-narrowing-aggregates.cpp2.output | 2 + ...ialization-safety-3-contract-violation.cpp | 4 +- .../mixed-initialization-safety-3.cpp | 4 +- .../mixed-lifetime-safety-pointer-init-4.cpp | 4 +- .../mixed-multiple-return-values.cpp | 6 +- .../test-results/mixed-out-destruction.cpp | 4 +- .../mixed-parameter-passing-generic-out.cpp | 2 +- .../pure2-autodiff-higher-order.cpp | 70 +++++------ .../test-results/pure2-autodiff.cpp | 110 +++++++++--------- ...-for-deferred-init-narrowing-constexpr.cpp | 60 ++++++++++ ...erred-init-narrowing-constexpr.cpp2.output | 2 + ...x-for-deferred-init-narrowing-literals.cpp | 48 ++++++++ ...ferred-init-narrowing-literals.cpp2.output | 2 + ...r-deferred-init-narrowing-matrix-error.cpp | 81 +++++++++++++ ...ed-init-narrowing-matrix-error.cpp2.output | 2 + ...erred-init-narrowing-negative-literals.cpp | 36 ++++++ ...it-narrowing-negative-literals.cpp2.output | 2 + ...x-for-name-lookup-and-value-decoration.cpp | 2 +- .../pure2-function-body-reflection.cpp | 6 +- .../test-results/pure2-function-typeids.cpp | 2 +- ...re2-initialization-safety-with-else-if.cpp | 18 +-- .../test-results/pure2-last-use.cpp | 10 +- ...k-up-parameter-across-unnamed-function.cpp | 2 +- regression-tests/test-results/pure2-print.cpp | 4 +- .../pure2-return-tuple-operator.cpp | 12 +- .../test-results/pure2-trailing-commas.cpp | 2 +- .../test-results/pure2-type-safety-1.cpp | 4 +- ...2-types-order-independence-and-nesting.cpp | 4 +- .../pure2-ufcs-member-access-and-chaining.cpp | 2 +- source/to_cpp1.h | 14 ++- 40 files changed, 746 insertions(+), 159 deletions(-) create mode 100644 regression-tests/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2 create mode 100644 regression-tests/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2 create mode 100644 regression-tests/pure2-bugfix-for-deferred-init-narrowing-literals.cpp2 create mode 100644 regression-tests/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2 create mode 100644 regression-tests/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2 create mode 100644 regression-tests/test-results/clang-19-c++20/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp.output create mode 100644 regression-tests/test-results/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp create mode 100644 regression-tests/test-results/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2.output create mode 100644 regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp create mode 100644 regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2.output create mode 100644 regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-literals.cpp create mode 100644 regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-literals.cpp2.output create mode 100644 regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp create mode 100644 regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2.output create mode 100644 regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp create mode 100644 regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2.output diff --git a/include/cpp2util.h b/include/cpp2util.h index 21764dd81..04a1eb147 100644 --- a/include/cpp2util.h +++ b/include/cpp2util.h @@ -1488,11 +1488,15 @@ class deferred_init { auto destroy() -> void { if (init) { t().~T(); } init = false; } public: + using value_type = T; + constexpr deferred_init() noexcept { } constexpr ~deferred_init() noexcept { destroy(); } constexpr auto value() noexcept -> T& { cpp2_default.enforce(init); return t(); } constexpr auto construct(auto&& ...args) -> void { cpp2_default.enforce(!init); new (&data) T{CPP2_FORWARD(args)...}; init = true; } + + constexpr auto construct_from(auto&& factory) -> void { cpp2_default.enforce(!init); new (&data) T(CPP2_FORWARD(factory)()); init = true; } }; @@ -1512,6 +1516,8 @@ class out { bool called_construct_ = false; public: + using value_type = T; + constexpr out(T* t_) noexcept : t{ t_}, has_t{true} { cpp2_default.enforce( t); } constexpr out(deferred_init* dt_) noexcept : dt{dt_}, has_t{false} { cpp2_default.enforce(dt); } constexpr out(out* ot_) noexcept : ot{ot_}, has_t{ot_->has_t} { cpp2_default.enforce(ot); @@ -1561,6 +1567,33 @@ class out { } } + constexpr auto construct_from(auto&& factory) -> void { + if (has_t || called_construct()) { + if constexpr (requires { *t = CPP2_FORWARD(factory)(); }) { + cpp2_default.enforce( t ); + *t = CPP2_FORWARD(factory)(); + } + else { + cpp2_default.report_violation("attempted to copy assign, but copy assignment is not available"); + } + } + else { + cpp2_default.enforce( dt ); + if (dt->init) { + if constexpr (requires { dt->value() = CPP2_FORWARD(factory)(); }) { + dt->value() = CPP2_FORWARD(factory)(); + } + else { + cpp2_default.report_violation("attempted to copy assign, but copy assignment is not available"); + } + } + else { + dt->construct_from(CPP2_FORWARD(factory)); + called_construct() = true; + } + } + } + constexpr auto value() noexcept -> T& { if (has_t) { cpp2_default.enforce( t ); diff --git a/regression-tests/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2 b/regression-tests/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2 new file mode 100644 index 000000000..c2fb44aea --- /dev/null +++ b/regression-tests/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2 @@ -0,0 +1,52 @@ +#include + +struct S { + std::int8_t x; + std::int8_t y; +}; + +struct Nested { + S left; + S right; +}; + +inline constexpr std::int16_t constexpr_i16 = 100; +inline constexpr std::int8_t constexpr_i8 = 8; + +main: () -> int = { + runtime_i8: i8 = 8; + + s_good0: S = (constexpr_i16, runtime_i8); + s_good: S; + s_good = (constexpr_i16, runtime_i8); + + s_reverse0: S = (runtime_i8, constexpr_i16); + s_reverse: S; + s_reverse = (runtime_i8, constexpr_i16); + + s_constexpr0: S = (constexpr_i16, constexpr_i16); + s_constexpr: S; + s_constexpr = (constexpr_i16, constexpr_i16); + + s_runtime0: S = (runtime_i8, runtime_i8); + s_runtime: S; + s_runtime = (runtime_i8, runtime_i8); + + nested0: Nested = ( + :S = (constexpr_i16, runtime_i8), + :S = (constexpr_i8, runtime_i8) + ); + nested: Nested; + nested = ( + :S = (constexpr_i16, runtime_i8), + :S = (constexpr_i8, runtime_i8) + ); + + assert(s_good0.x == 100 && s_good.y == 8); + assert(s_reverse0.x == 8 && s_reverse.y == 100); + assert(s_constexpr0.x == 100 && s_constexpr.y == 100); + assert(s_runtime0.x == 8 && s_runtime.y == 8); + assert(nested0.left.x == 100 && nested.right.y == 8); + + return 0; +} diff --git a/regression-tests/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2 b/regression-tests/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2 new file mode 100644 index 000000000..f0ccebc51 --- /dev/null +++ b/regression-tests/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2 @@ -0,0 +1,31 @@ +value: i32 == 20; + +foo: () -> i32 == 20; + +add: (x: i32, y: i32) -> i32 == x + y; + +main: () -> int = { + a0: i8 = value + 100; + a: i8; + a = value + 100; + + b0: i8 = foo() + 100; + b: i8; + b = foo() + 100; + + c0: i16 = add(value, foo()) + 100; + c: i16; + c = add(value, foo()) + 100; + + local: i32 == 10; + + d0: i16 = add(local, foo()) * 2 + value; + d: i16; + d = add(local, foo()) * 2 + value; + + e0: std::array = (value + 100, foo() + 100, add(local, foo())); + e: std::array; + e = (value + 100, foo() + 100, add(local, foo())); + + return 0; +} diff --git a/regression-tests/pure2-bugfix-for-deferred-init-narrowing-literals.cpp2 b/regression-tests/pure2-bugfix-for-deferred-init-narrowing-literals.cpp2 new file mode 100644 index 000000000..921b8fd11 --- /dev/null +++ b/regression-tests/pure2-bugfix-for-deferred-init-narrowing-literals.cpp2 @@ -0,0 +1,27 @@ +main: () -> int = { + a0: u8 = 'a'; + a: u8; + a = 'a'; + + b0: i8 = 1; + b: i8; + b = 1; + + c0: u8 = 2; + c: u8; + c = 2; + + d0: i16 = 3; + d: i16; + d = 3; + + e0: u16 = 4; + e: u16; + e = 4; + + f0: std::array = (5, 6, 7); + f: std::array; + f = (5, 6, 7); + + return 0; +} diff --git a/regression-tests/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2 b/regression-tests/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2 new file mode 100644 index 000000000..93eaa089e --- /dev/null +++ b/regression-tests/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2 @@ -0,0 +1,54 @@ +// Target type is {i8, i8}. We try every pair from: +// ce_i8, ce_i16, rt_i8, rt_i16 +// = 4 x 4 = 16 combinations. +// +// Constexpr sources must appear by name in the initializer, otherwise they +// stop being constant expressions and every i16 case would fail. + +ce_i8: i8 == 8; +ce_i16: i16 == 8; + +try_all_combinations: (rt_i8: i8, rt_i16: i16) = { + a00: std::array; + a00 = (ce_i8, ce_i8); + a01: std::array; + a01 = (ce_i8, ce_i16); + a02: std::array; + a02 = (ce_i8, rt_i8); + a03: std::array; + a03 = (ce_i8, rt_i16); // fail: runtime i16 -> i8 + + a10: std::array; + a10 = (ce_i16, ce_i8); + a11: std::array; + a11 = (ce_i16, ce_i16); + a12: std::array; + a12 = (ce_i16, rt_i8); + a13: std::array; + a13 = (ce_i16, rt_i16); // fail: runtime i16 -> i8 + + a20: std::array; + a20 = (rt_i8, ce_i8); + a21: std::array; + a21 = (rt_i8, ce_i16); + a22: std::array; + a22 = (rt_i8, rt_i8); + a23: std::array; + a23 = (rt_i8, rt_i16); // fail: runtime i16 -> i8 + + a30: std::array; + a30 = (rt_i16, ce_i8); // fail: runtime i16 -> i8 + a31: std::array; + a31 = (rt_i16, ce_i16); // fail: runtime i16 -> i8 + a32: std::array; + a32 = (rt_i16, rt_i8); // fail: runtime i16 -> i8 + a33: std::array; + a33 = (rt_i16, rt_i16); // fail: runtime i16 -> i8 +} + +main: () -> int = { + rt_i8: i8 = 8; + rt_i16: i16 = 8; + try_all_combinations(rt_i8, rt_i16); + return 0; +} diff --git a/regression-tests/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2 b/regression-tests/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2 new file mode 100644 index 000000000..be0b196a5 --- /dev/null +++ b/regression-tests/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2 @@ -0,0 +1,15 @@ +main: () -> int = { + a0: i8 = -1; + a: i8; + a = -1; + + b0: i16 = -2; + b: i16; + b = -2; + + c0: std::array = (-3, -4, -5); + c: std::array; + c = (-3, -4, -5); + + return 0; +} diff --git a/regression-tests/test-results/clang-19-c++20/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp.output b/regression-tests/test-results/clang-19-c++20/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp.output new file mode 100644 index 000000000..04bec2b00 --- /dev/null +++ b/regression-tests/test-results/clang-19-c++20/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp.output @@ -0,0 +1,57 @@ +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:19:125: error: non-constant-expression cannot be narrowed from type 'cpp2::impl::in' (aka 'const short') to 'signed char' in initializer list [-Wc++11-narrowing] + 19 | a03.construct_from([&]() -> typename CPP2_TYPEOF(a03)::value_type { return typename CPP2_TYPEOF(a03)::value_type{ce_i8, rt_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:19:125: note: insert an explicit cast to silence this issue + 19 | a03.construct_from([&]() -> typename CPP2_TYPEOF(a03)::value_type { return typename CPP2_TYPEOF(a03)::value_type{ce_i8, rt_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ + | static_cast( ) +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:28:126: error: non-constant-expression cannot be narrowed from type 'cpp2::impl::in' (aka 'const short') to 'signed char' in initializer list [-Wc++11-narrowing] + 28 | a13.construct_from([&]() -> typename CPP2_TYPEOF(a13)::value_type { return typename CPP2_TYPEOF(a13)::value_type{ce_i16, rt_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:28:126: note: insert an explicit cast to silence this issue + 28 | a13.construct_from([&]() -> typename CPP2_TYPEOF(a13)::value_type { return typename CPP2_TYPEOF(a13)::value_type{ce_i16, rt_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ + | static_cast( ) +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:37:125: error: non-constant-expression cannot be narrowed from type 'cpp2::impl::in' (aka 'const short') to 'signed char' in initializer list [-Wc++11-narrowing] + 37 | a23.construct_from([&]() -> typename CPP2_TYPEOF(a23)::value_type { return typename CPP2_TYPEOF(a23)::value_type{rt_i8, rt_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:37:125: note: insert an explicit cast to silence this issue + 37 | a23.construct_from([&]() -> typename CPP2_TYPEOF(a23)::value_type { return typename CPP2_TYPEOF(a23)::value_type{rt_i8, rt_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ + | static_cast( ) +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:40:118: error: non-constant-expression cannot be narrowed from type 'cpp2::impl::in' (aka 'const short') to 'signed char' in initializer list [-Wc++11-narrowing] + 40 | a30.construct_from([&]() -> typename CPP2_TYPEOF(a30)::value_type { return typename CPP2_TYPEOF(a30)::value_type{rt_i16, ce_i8}; });// fail: runtime i16 -> i8 + | ^~~~~~ +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:40:118: note: insert an explicit cast to silence this issue + 40 | a30.construct_from([&]() -> typename CPP2_TYPEOF(a30)::value_type { return typename CPP2_TYPEOF(a30)::value_type{rt_i16, ce_i8}; });// fail: runtime i16 -> i8 + | ^~~~~~ + | static_cast( ) +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:42:118: error: non-constant-expression cannot be narrowed from type 'cpp2::impl::in' (aka 'const short') to 'signed char' in initializer list [-Wc++11-narrowing] + 42 | a31.construct_from([&]() -> typename CPP2_TYPEOF(a31)::value_type { return typename CPP2_TYPEOF(a31)::value_type{rt_i16, ce_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:42:118: note: insert an explicit cast to silence this issue + 42 | a31.construct_from([&]() -> typename CPP2_TYPEOF(a31)::value_type { return typename CPP2_TYPEOF(a31)::value_type{rt_i16, ce_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ + | static_cast( ) +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:44:118: error: non-constant-expression cannot be narrowed from type 'cpp2::impl::in' (aka 'const short') to 'signed char' in initializer list [-Wc++11-narrowing] + 44 | a32.construct_from([&]() -> typename CPP2_TYPEOF(a32)::value_type { return typename CPP2_TYPEOF(a32)::value_type{rt_i16, rt_i8}; });// fail: runtime i16 -> i8 + | ^~~~~~ +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:44:118: note: insert an explicit cast to silence this issue + 44 | a32.construct_from([&]() -> typename CPP2_TYPEOF(a32)::value_type { return typename CPP2_TYPEOF(a32)::value_type{rt_i16, rt_i8}; });// fail: runtime i16 -> i8 + | ^~~~~~ + | static_cast( ) +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:46:118: error: non-constant-expression cannot be narrowed from type 'cpp2::impl::in' (aka 'const short') to 'signed char' in initializer list [-Wc++11-narrowing] + 46 | a33.construct_from([&]() -> typename CPP2_TYPEOF(a33)::value_type { return typename CPP2_TYPEOF(a33)::value_type{rt_i16, rt_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:46:118: note: insert an explicit cast to silence this issue + 46 | a33.construct_from([&]() -> typename CPP2_TYPEOF(a33)::value_type { return typename CPP2_TYPEOF(a33)::value_type{rt_i16, rt_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ + | static_cast( ) +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:46:126: error: non-constant-expression cannot be narrowed from type 'cpp2::impl::in' (aka 'const short') to 'signed char' in initializer list [-Wc++11-narrowing] + 46 | a33.construct_from([&]() -> typename CPP2_TYPEOF(a33)::value_type { return typename CPP2_TYPEOF(a33)::value_type{rt_i16, rt_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2:46:126: note: insert an explicit cast to silence this issue + 46 | a33.construct_from([&]() -> typename CPP2_TYPEOF(a33)::value_type { return typename CPP2_TYPEOF(a33)::value_type{rt_i16, rt_i16}; });// fail: runtime i16 -> i8 + | ^~~~~~ + | static_cast( ) +8 errors generated. diff --git a/regression-tests/test-results/clang-19-c++23-libcpp/mixed-lifetime-safety-pointer-init-4.cpp b/regression-tests/test-results/clang-19-c++23-libcpp/mixed-lifetime-safety-pointer-init-4.cpp index 7351d0900..86638fc40 100644 --- a/regression-tests/test-results/clang-19-c++23-libcpp/mixed-lifetime-safety-pointer-init-4.cpp +++ b/regression-tests/test-results/clang-19-c++23-libcpp/mixed-lifetime-safety-pointer-init-4.cpp @@ -41,10 +41,10 @@ bool flip_a_coin() { // ... more code ... if (flip_a_coin()) { - p.construct(&y); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{&y}; }); } else { - p.construct(&x); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{&x}; }); } print_and_decorate(*cpp2::impl::assert_not_null(cpp2::move(p.value()))); diff --git a/regression-tests/test-results/mixed-autodiff-taylor.cpp b/regression-tests/test-results/mixed-autodiff-taylor.cpp index 0d9798c13..fe441a003 100644 --- a/regression-tests/test-results/mixed-autodiff-taylor.cpp +++ b/regression-tests/test-results/mixed-autodiff-taylor.cpp @@ -85,8 +85,8 @@ auto main() -> int; cpp2::impl::deferred_init y0; cpp2::impl::deferred_init y; #line 7 "mixed-autodiff-taylor.cpp2" - y.construct(CPP2_UFCS(add)(x, x, x0, x0)); - y0.construct(x0 + x0); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{CPP2_UFCS(add)(x, x, x0, x0)}; }); + y0.construct_from([&]() -> typename CPP2_TYPEOF(y0)::value_type { return typename CPP2_TYPEOF(y0)::value_type{x0 + x0}; }); return { std::move(y0.value()), std::move(y.value()) }; } #line 11 "mixed-autodiff-taylor.cpp2" @@ -94,8 +94,8 @@ return { std::move(y0.value()), std::move(y.value()) }; } cpp2::impl::deferred_init y0; cpp2::impl::deferred_init y; #line 12 "mixed-autodiff-taylor.cpp2" - y0.construct(0.0); - y.construct(taylor()); + y0.construct_from([&]() -> typename CPP2_TYPEOF(y0)::value_type { return typename CPP2_TYPEOF(y0)::value_type{0.0}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{taylor()}; }); y.value() = CPP2_UFCS(sub)(y.value(), x, y0.value(), x0); y0.value() = y0.value() - x0; @@ -106,8 +106,8 @@ return { std::move(y0.value()), std::move(y.value()) }; } cpp2::impl::deferred_init y0; cpp2::impl::deferred_init y; #line 20 "mixed-autodiff-taylor.cpp2" - y0.construct(x0); - y.construct(x); + y0.construct_from([&]() -> typename CPP2_TYPEOF(y0)::value_type { return typename CPP2_TYPEOF(y0)::value_type{x0}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{x}; }); { auto i{0}; @@ -128,8 +128,8 @@ auto i{0}; cpp2::impl::deferred_init y0; cpp2::impl::deferred_init y; #line 31 "mixed-autodiff-taylor.cpp2" - y0.construct(1.0); - y.construct(taylor()); + y0.construct_from([&]() -> typename CPP2_TYPEOF(y0)::value_type { return typename CPP2_TYPEOF(y0)::value_type{1.0}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{taylor()}; }); y.value() = CPP2_UFCS(div)(y.value(), x, y0.value(), x0); y0.value() /= CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y0.value()),x0); @@ -140,8 +140,8 @@ return { std::move(y0.value()), std::move(y.value()) }; } cpp2::impl::deferred_init y0; cpp2::impl::deferred_init y; #line 39 "mixed-autodiff-taylor.cpp2" - y0.construct(sqrt(x0)); - y.construct(CPP2_UFCS(sqrt)(x, x0)); + y0.construct_from([&]() -> typename CPP2_TYPEOF(y0)::value_type { return typename CPP2_TYPEOF(y0)::value_type{sqrt(x0)}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{CPP2_UFCS(sqrt)(x, x0)}; }); return { std::move(y0.value()), std::move(y.value()) }; } #line 43 "mixed-autodiff-taylor.cpp2" @@ -149,8 +149,8 @@ return { std::move(y0.value()), std::move(y.value()) }; } cpp2::impl::deferred_init y0; cpp2::impl::deferred_init y; #line 44 "mixed-autodiff-taylor.cpp2" - y0.construct(log(x0)); - y.construct(CPP2_UFCS(log)(x, x0)); + y0.construct_from([&]() -> typename CPP2_TYPEOF(y0)::value_type { return typename CPP2_TYPEOF(y0)::value_type{log(x0)}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{CPP2_UFCS(log)(x, x0)}; }); return { std::move(y0.value()), std::move(y.value()) }; } #line 48 "mixed-autodiff-taylor.cpp2" @@ -158,8 +158,8 @@ return { std::move(y0.value()), std::move(y.value()) }; } cpp2::impl::deferred_init y0; cpp2::impl::deferred_init y; #line 49 "mixed-autodiff-taylor.cpp2" - y0.construct(exp(x0)); - y.construct(CPP2_UFCS(exp)(x, x0)); + y0.construct_from([&]() -> typename CPP2_TYPEOF(y0)::value_type { return typename CPP2_TYPEOF(y0)::value_type{exp(x0)}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{CPP2_UFCS(exp)(x, x0)}; }); return { std::move(y0.value()), std::move(y.value()) }; } #line 53 "mixed-autodiff-taylor.cpp2" @@ -167,8 +167,8 @@ return { std::move(y0.value()), std::move(y.value()) }; } cpp2::impl::deferred_init y0; cpp2::impl::deferred_init y; #line 54 "mixed-autodiff-taylor.cpp2" - y0.construct(sin(x0)); - y.construct(CPP2_UFCS(sin)(x, x0)); + y0.construct_from([&]() -> typename CPP2_TYPEOF(y0)::value_type { return typename CPP2_TYPEOF(y0)::value_type{sin(x0)}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{CPP2_UFCS(sin)(x, x0)}; }); return { std::move(y0.value()), std::move(y.value()) }; } #line 58 "mixed-autodiff-taylor.cpp2" @@ -176,8 +176,8 @@ return { std::move(y0.value()), std::move(y.value()) }; } cpp2::impl::deferred_init y0; cpp2::impl::deferred_init y; #line 59 "mixed-autodiff-taylor.cpp2" - y0.construct(cos(x0)); - y.construct(CPP2_UFCS(cos)(x, x0)); + y0.construct_from([&]() -> typename CPP2_TYPEOF(y0)::value_type { return typename CPP2_TYPEOF(y0)::value_type{cos(x0)}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{CPP2_UFCS(cos)(x, x0)}; }); return { std::move(y0.value()), std::move(y.value()) }; } #line 63 "mixed-autodiff-taylor.cpp2" diff --git a/regression-tests/test-results/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp b/regression-tests/test-results/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp new file mode 100644 index 000000000..fd8a76768 --- /dev/null +++ b/regression-tests/test-results/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp @@ -0,0 +1,75 @@ +#include + + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2" + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2" +#line 2 "mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2" + +struct S { + std::int8_t x; + std::int8_t y; +}; + +struct Nested { + S left; + S right; +}; + +inline constexpr std::int16_t constexpr_i16 = 100; +inline constexpr std::int8_t constexpr_i8 = 8; + +#line 16 "mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2" +[[nodiscard]] auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2" + +#line 16 "mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2" +[[nodiscard]] auto main() -> int{ + cpp2::i8 runtime_i8 {8}; + + S s_good0 {constexpr_i16, runtime_i8}; + cpp2::impl::deferred_init s_good; + s_good.construct_from([&]() -> typename CPP2_TYPEOF(s_good)::value_type { return typename CPP2_TYPEOF(s_good)::value_type{constexpr_i16, runtime_i8}; }); + + S s_reverse0 {runtime_i8, constexpr_i16}; + cpp2::impl::deferred_init s_reverse; + s_reverse.construct_from([&]() -> typename CPP2_TYPEOF(s_reverse)::value_type { return typename CPP2_TYPEOF(s_reverse)::value_type{runtime_i8, constexpr_i16}; }); + + S s_constexpr0 {constexpr_i16, constexpr_i16}; + cpp2::impl::deferred_init s_constexpr; + s_constexpr.construct_from([&]() -> typename CPP2_TYPEOF(s_constexpr)::value_type { return typename CPP2_TYPEOF(s_constexpr)::value_type{constexpr_i16, constexpr_i16}; }); + + S s_runtime0 {runtime_i8, runtime_i8}; + cpp2::impl::deferred_init s_runtime; + s_runtime.construct_from([&]() -> typename CPP2_TYPEOF(s_runtime)::value_type { return typename CPP2_TYPEOF(s_runtime)::value_type{runtime_i8, runtime_i8}; }); + + Nested nested0 { + S{constexpr_i16, runtime_i8}, + S{constexpr_i8, runtime_i8}}; + + cpp2::impl::deferred_init nested; + nested.construct_from([&]() -> typename CPP2_TYPEOF(nested)::value_type { return typename CPP2_TYPEOF(nested)::value_type{ + S{constexpr_i16, runtime_i8}, + S{constexpr_i8, cpp2::move(runtime_i8)}}; }); + +#line 45 "mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2" + if (cpp2::cpp2_default.is_active() && !(cpp2::move(s_good0).x == 100 && cpp2::move(s_good.value()).y == 8) ) { cpp2::cpp2_default.report_violation(""); } + if (cpp2::cpp2_default.is_active() && !(cpp2::move(s_reverse0).x == 8 && cpp2::move(s_reverse.value()).y == 100) ) { cpp2::cpp2_default.report_violation(""); } + if (cpp2::cpp2_default.is_active() && !(cpp2::move(s_constexpr0).x == 100 && cpp2::move(s_constexpr.value()).y == 100) ) { cpp2::cpp2_default.report_violation(""); } + if (cpp2::cpp2_default.is_active() && !(cpp2::move(s_runtime0).x == 8 && cpp2::move(s_runtime.value()).y == 8) ) { cpp2::cpp2_default.report_violation(""); } + if (cpp2::cpp2_default.is_active() && !(cpp2::move(nested0).left.x == 100 && cpp2::move(nested.value()).right.y == 8) ) { cpp2::cpp2_default.report_violation(""); } + + return 0; +} + diff --git a/regression-tests/test-results/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2.output b/regression-tests/test-results/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2.output new file mode 100644 index 000000000..9e4fb3177 --- /dev/null +++ b/regression-tests/test-results/mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2.output @@ -0,0 +1,2 @@ +mixed-bugfix-for-deferred-init-narrowing-aggregates.cpp2... ok (mixed Cpp1/Cpp2, Cpp2 code passes safety checks) + diff --git a/regression-tests/test-results/mixed-initialization-safety-3-contract-violation.cpp b/regression-tests/test-results/mixed-initialization-safety-3-contract-violation.cpp index de11f8434..d58f675c5 100644 --- a/regression-tests/test-results/mixed-initialization-safety-3-contract-violation.cpp +++ b/regression-tests/test-results/mixed-initialization-safety-3-contract-violation.cpp @@ -48,7 +48,7 @@ bool flip_a_coin() { cpp2::impl::deferred_init x; // note: uninitialized! if (flip_a_coin()) { - x.construct("xyzzy"); + x.construct_from([&]() -> typename CPP2_TYPEOF(x)::value_type { return typename CPP2_TYPEOF(x)::value_type{"xyzzy"}; }); }else { fill(cpp2::impl::out(&x), "plugh", 40);// note: constructs x! } @@ -65,7 +65,7 @@ auto fill( { if (cpp2::cpp2_default.is_active() && !(cpp2::impl::cmp_greater_eq(CPP2_UFCS(ssize)(value),count)) ) { cpp2::cpp2_default.report_violation(CPP2_CONTRACT_MSG("fill: value must contain at least count elements")); } #line 25 "mixed-initialization-safety-3-contract-violation.cpp2" - x.construct(CPP2_UFCS(substr)(value, 0, count)); + x.construct_from([&]() -> typename CPP2_TYPEOF(x)::value_type { return typename CPP2_TYPEOF(x)::value_type{CPP2_UFCS(substr)(value, 0, count)}; }); } #line 28 "mixed-initialization-safety-3-contract-violation.cpp2" diff --git a/regression-tests/test-results/mixed-initialization-safety-3.cpp b/regression-tests/test-results/mixed-initialization-safety-3.cpp index 568830922..e7d6c943f 100644 --- a/regression-tests/test-results/mixed-initialization-safety-3.cpp +++ b/regression-tests/test-results/mixed-initialization-safety-3.cpp @@ -42,7 +42,7 @@ auto print_decorated(auto const& x) -> void; cpp2::impl::deferred_init x; // note: uninitialized! if (flip_a_coin()) { - x.construct("xyzzy"); + x.construct_from([&]() -> typename CPP2_TYPEOF(x)::value_type { return typename CPP2_TYPEOF(x)::value_type{"xyzzy"}; }); }else { fill(cpp2::impl::out(&x), "plugh", 40);// note: constructs x! } @@ -59,7 +59,7 @@ auto fill( { if (cpp2::cpp2_default.is_active() && !(cpp2::impl::cmp_greater_eq(CPP2_UFCS(ssize)(value),count)) ) { cpp2::cpp2_default.report_violation(CPP2_CONTRACT_MSG("fill: value must contain at least count elements")); } #line 23 "mixed-initialization-safety-3.cpp2" - x.construct(CPP2_UFCS(substr)(value, 0, count)); + x.construct_from([&]() -> typename CPP2_TYPEOF(x)::value_type { return typename CPP2_TYPEOF(x)::value_type{CPP2_UFCS(substr)(value, 0, count)}; }); } #line 26 "mixed-initialization-safety-3.cpp2" diff --git a/regression-tests/test-results/mixed-lifetime-safety-pointer-init-4.cpp b/regression-tests/test-results/mixed-lifetime-safety-pointer-init-4.cpp index 7351d0900..86638fc40 100644 --- a/regression-tests/test-results/mixed-lifetime-safety-pointer-init-4.cpp +++ b/regression-tests/test-results/mixed-lifetime-safety-pointer-init-4.cpp @@ -41,10 +41,10 @@ bool flip_a_coin() { // ... more code ... if (flip_a_coin()) { - p.construct(&y); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{&y}; }); } else { - p.construct(&x); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{&x}; }); } print_and_decorate(*cpp2::impl::assert_not_null(cpp2::move(p.value()))); diff --git a/regression-tests/test-results/mixed-multiple-return-values.cpp b/regression-tests/test-results/mixed-multiple-return-values.cpp index c168d0b9b..b35e2de7c 100644 --- a/regression-tests/test-results/mixed-multiple-return-values.cpp +++ b/regression-tests/test-results/mixed-multiple-return-values.cpp @@ -50,14 +50,14 @@ bool flip_a_coin() { // note: i and s are uninitialized! #line 9 "mixed-multiple-return-values.cpp2" - i.construct(10); + i.construct_from([&]() -> typename CPP2_TYPEOF(i)::value_type { return typename CPP2_TYPEOF(i)::value_type{10}; }); // the standard mandates that std::mt19937()() == 3499211612 if (flip_a_coin()) { - s.construct("xyzzy"); + s.construct_from([&]() -> typename CPP2_TYPEOF(s)::value_type { return typename CPP2_TYPEOF(s)::value_type{"xyzzy"}; }); } else { - s.construct("plugh"); + s.construct_from([&]() -> typename CPP2_TYPEOF(s)::value_type { return typename CPP2_TYPEOF(s)::value_type{"plugh"}; }); } return { std::move(i.value()), std::move(s.value()) }; diff --git a/regression-tests/test-results/mixed-out-destruction.cpp b/regression-tests/test-results/mixed-out-destruction.cpp index dc38874e6..e7b84d345 100644 --- a/regression-tests/test-results/mixed-out-destruction.cpp +++ b/regression-tests/test-results/mixed-out-destruction.cpp @@ -60,7 +60,7 @@ int main() { #line 22 "mixed-out-destruction.cpp2" auto f00() -> void { C auto_1 {"f00"}; cpp2::impl::deferred_init x; f01(cpp2::impl::out(&x));} #line 23 "mixed-out-destruction.cpp2" -auto f01(cpp2::impl::out x) -> void{C auto_1 {"f01"}; x.construct();throw_1();} +auto f01(cpp2::impl::out x) -> void{C auto_1 {"f01"}; x.construct_from([&]() -> typename CPP2_TYPEOF(x)::value_type { return typename CPP2_TYPEOF(x)::value_type{}; });throw_1();} #line 27 "mixed-out-destruction.cpp2" auto f10() -> void { C auto_1 {"f10"}; cpp2::impl::deferred_init x; f11(cpp2::impl::out(&x));} @@ -71,5 +71,5 @@ auto f12(cpp2::impl::out x) -> void{C auto_1 {"f12"}; f13(cpp2::impl::out(&x) #line 30 "mixed-out-destruction.cpp2" auto f13(cpp2::impl::out x) -> void{C auto_1 {"f13"}; f14(cpp2::impl::out(&x));} #line 31 "mixed-out-destruction.cpp2" -auto f14(cpp2::impl::out x) -> void{C auto_1 {"f14"}; x.construct();} +auto f14(cpp2::impl::out x) -> void{C auto_1 {"f14"}; x.construct_from([&]() -> typename CPP2_TYPEOF(x)::value_type { return typename CPP2_TYPEOF(x)::value_type{}; });} diff --git a/regression-tests/test-results/mixed-parameter-passing-generic-out.cpp b/regression-tests/test-results/mixed-parameter-passing-generic-out.cpp index ca2b7e5c1..45291bc40 100644 --- a/regression-tests/test-results/mixed-parameter-passing-generic-out.cpp +++ b/regression-tests/test-results/mixed-parameter-passing-generic-out.cpp @@ -36,7 +36,7 @@ auto f(auto x_) -> void; auto f(auto x_) -> void{ auto x = cpp2::impl::out(x_); #line 12 "mixed-parameter-passing-generic-out.cpp2" - x.construct(42); + x.construct_from([&]() -> typename CPP2_TYPEOF(x)::value_type { return typename CPP2_TYPEOF(x)::value_type{42}; }); } #line 15 "mixed-parameter-passing-generic-out.cpp2" diff --git a/regression-tests/test-results/pure2-autodiff-higher-order.cpp b/regression-tests/test-results/pure2-autodiff-higher-order.cpp index 282c36129..8b849323e 100644 --- a/regression-tests/test-results/pure2-autodiff-higher-order.cpp +++ b/regression-tests/test-results/pure2-autodiff-higher-order.cpp @@ -374,7 +374,7 @@ namespace ad_name { [[nodiscard]] auto func_outer(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_ret{ cpp2::impl::deferred_init ret; #line 7 "pure2-autodiff-higher-order.cpp2" - ret.construct(x + y); + ret.construct_from([&]() -> typename CPP2_TYPEOF(ret)::value_type { return typename CPP2_TYPEOF(ret)::value_type{x + y}; }); return std::move(ret.value()); } #line 13 "pure2-autodiff-higher-order.cpp2" @@ -401,133 +401,133 @@ return std::move(ret.value()); } [[nodiscard]] auto ad_test::add_1(cpp2::impl::in x, cpp2::impl::in y) -> add_1_ret{ cpp2::impl::deferred_init r; #line 21 "pure2-autodiff-higher-order.cpp2" - r.construct(x + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y}; }); return std::move(r.value()); } #line 24 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::add_2(cpp2::impl::in x, cpp2::impl::in y) -> add_2_ret{ cpp2::impl::deferred_init r; #line 25 "pure2-autodiff-higher-order.cpp2" - r.construct(x + y + x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y + x}; }); return std::move(r.value()); } #line 28 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::sub_1(cpp2::impl::in x, cpp2::impl::in y) -> sub_1_ret{ cpp2::impl::deferred_init r; #line 29 "pure2-autodiff-higher-order.cpp2" - r.construct(x - y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x - y}; }); return std::move(r.value()); } #line 32 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::sub_2(cpp2::impl::in x, cpp2::impl::in y) -> sub_2_ret{ cpp2::impl::deferred_init r; #line 33 "pure2-autodiff-higher-order.cpp2" - r.construct(x - y - x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x - y - x}; }); return std::move(r.value()); } #line 36 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::add_sub_2(cpp2::impl::in x, cpp2::impl::in y) -> add_sub_2_ret{ cpp2::impl::deferred_init r; #line 37 "pure2-autodiff-higher-order.cpp2" - r.construct(x + y - x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y - x}; }); return std::move(r.value()); } #line 40 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::mul_1(cpp2::impl::in x, cpp2::impl::in y) -> mul_1_ret{ cpp2::impl::deferred_init r; #line 41 "pure2-autodiff-higher-order.cpp2" - r.construct(x * y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * y}; }); return std::move(r.value()); } #line 44 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::mul_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_2_ret{ cpp2::impl::deferred_init r; #line 45 "pure2-autodiff-higher-order.cpp2" - r.construct(x * y * x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * y * x}; }); return std::move(r.value()); } #line 48 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::div_1(cpp2::impl::in x, cpp2::impl::in y) -> div_1_ret{ cpp2::impl::deferred_init r; #line 49 "pure2-autodiff-higher-order.cpp2" - r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)}; }); return std::move(r.value()); } #line 52 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::div_2(cpp2::impl::in x, cpp2::impl::in y) -> div_2_ret{ cpp2::impl::deferred_init r; #line 53 "pure2-autodiff-higher-order.cpp2" - r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),y)}; }); return std::move(r.value()); } #line 56 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::mul_div_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_div_2_ret{ cpp2::impl::deferred_init r; #line 57 "pure2-autodiff-higher-order.cpp2" - r.construct(x * y / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),x)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * y / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),x)}; }); return std::move(r.value()); } #line 60 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::mul_add(cpp2::impl::in x, cpp2::impl::in y) -> mul_add_ret{ cpp2::impl::deferred_init r; #line 61 "pure2-autodiff-higher-order.cpp2" - r.construct(x * (x + y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * (x + y)}; }); return std::move(r.value()); } #line 64 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::add_mul(cpp2::impl::in x, cpp2::impl::in y) -> add_mul_ret{ cpp2::impl::deferred_init r; #line 65 "pure2-autodiff-higher-order.cpp2" - r.construct(x + x * y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + x * y}; }); return std::move(r.value()); } #line 68 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::prefix_add(cpp2::impl::in x, cpp2::impl::in y) -> prefix_add_ret{ cpp2::impl::deferred_init r; #line 69 "pure2-autodiff-higher-order.cpp2" - r.construct(+x + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{+x + y}; }); return std::move(r.value()); } #line 72 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::prefix_sub(cpp2::impl::in x, cpp2::impl::in y) -> prefix_sub_ret{ cpp2::impl::deferred_init r; #line 73 "pure2-autodiff-higher-order.cpp2" - r.construct(-x + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{-x + y}; }); return std::move(r.value()); } #line 76 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::func(cpp2::impl::in x, cpp2::impl::in y) -> func_ret{ cpp2::impl::deferred_init ret; #line 77 "pure2-autodiff-higher-order.cpp2" - ret.construct(x + y); + ret.construct_from([&]() -> typename CPP2_TYPEOF(ret)::value_type { return typename CPP2_TYPEOF(ret)::value_type{x + y}; }); return std::move(ret.value()); } #line 80 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::func_call(cpp2::impl::in x, cpp2::impl::in y) -> func_call_ret{ cpp2::impl::deferred_init r; #line 81 "pure2-autodiff-higher-order.cpp2" - r.construct(x * func(x, y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * func(x, y)}; }); return std::move(r.value()); } #line 84 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::func_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_call_ret{ cpp2::impl::deferred_init r; #line 85 "pure2-autodiff-higher-order.cpp2" - r.construct(x * func_outer(x, y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * func_outer(x, y)}; }); return std::move(r.value()); } #line 88 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::sin_call(cpp2::impl::in x, cpp2::impl::in y) -> sin_call_ret{ cpp2::impl::deferred_init r; #line 89 "pure2-autodiff-higher-order.cpp2" - r.construct(sin(x - y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{sin(x - y)}; }); return std::move(r.value()); } #line 92 "pure2-autodiff-higher-order.cpp2" [[nodiscard]] auto ad_test::if_branch(cpp2::impl::in x, cpp2::impl::in y) -> if_branch_ret{ cpp2::impl::deferred_init r; #line 93 "pure2-autodiff-higher-order.cpp2" - r.construct(x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x}; }); if (cpp2::impl::cmp_less(x,0.0)) { r.value() = y; @@ -539,10 +539,10 @@ return std::move(ret.value()); } cpp2::impl::deferred_init r; #line 101 "pure2-autodiff-higher-order.cpp2" if (cpp2::impl::cmp_less(x,0.0)) { - r.construct(y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{y}; }); } else { - r.construct(x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x}; }); }return std::move(r.value()); } @@ -557,7 +557,7 @@ return std::move(ret.value()); } #line 114 "pure2-autodiff-higher-order.cpp2" double t {x + y}; - r.construct(cpp2::move(t)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t)}; }); return std::move(r.value()); } #line 119 "pure2-autodiff-higher-order.cpp2" @@ -565,7 +565,7 @@ return std::move(ret.value()); } cpp2::impl::deferred_init r; #line 120 "pure2-autodiff-higher-order.cpp2" int i {}; // TODO: Handle as passive when type information on call side is available. - r.construct(x + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y}; }); i = 2; static_cast(cpp2::move(i)); @@ -578,7 +578,7 @@ return std::move(ret.value()); } auto t {0.0}; t = x + y; - r.construct(cpp2::move(t)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t)}; }); return std::move(r.value()); } #line 134 "pure2-autodiff-higher-order.cpp2" @@ -588,7 +588,7 @@ return std::move(ret.value()); } double t {}; t = x + y; - r.construct(cpp2::move(t)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t)}; }); return std::move(r.value()); } #line 141 "pure2-autodiff-higher-order.cpp2" @@ -596,9 +596,9 @@ return std::move(ret.value()); } cpp2::impl::deferred_init r; #line 142 "pure2-autodiff-higher-order.cpp2" cpp2::impl::deferred_init t; - t.construct(x + y); + t.construct_from([&]() -> typename CPP2_TYPEOF(t)::value_type { return typename CPP2_TYPEOF(t)::value_type{x + y}; }); - r.construct(cpp2::move(t.value())); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t.value())}; }); return std::move(r.value()); } #line 148 "pure2-autodiff-higher-order.cpp2" @@ -607,7 +607,7 @@ return std::move(ret.value()); } #line 149 "pure2-autodiff-higher-order.cpp2" int i {0}; - r.construct(x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x}; }); for( ; cpp2::impl::cmp_less(i,2); (i += 1) ) { r.value() = r.value() + y; }return std::move(r.value()); @@ -619,7 +619,7 @@ return std::move(ret.value()); } #line 158 "pure2-autodiff-higher-order.cpp2" int i {0}; - r.construct(x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x}; }); do { r.value() = r.value() + y; } while ( [&]{ @@ -636,7 +636,7 @@ return std::move(ret.value()); } CPP2_UFCS(push_back)(v, x); CPP2_UFCS(push_back)(v, y); - r.construct(0.0); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{0.0}; }); for ( auto const& t : cpp2::move(v) ) { @@ -651,7 +651,7 @@ return std::move(ret.value()); } type_outer t {}; t.a = x; - r.construct(cpp2::move(t).a + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t).a + y}; }); return std::move(r.value()); } #line 189 "pure2-autodiff-higher-order.cpp2" @@ -661,7 +661,7 @@ return std::move(ret.value()); } type_outer t {}; t.a = x; - r.construct(CPP2_UFCS(add)(cpp2::move(t), y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{CPP2_UFCS(add)(cpp2::move(t), y)}; }); return std::move(r.value()); } [[nodiscard]] auto ad_test::add_1_d(cpp2::impl::in x, cpp2::impl::in> x_d, cpp2::impl::in y, cpp2::impl::in> y_d) -> add_1_d_ret{ @@ -920,8 +920,8 @@ cpp2::taylor t_d {}; cpp2::impl::deferred_init> t_d; cpp2::impl::deferred_init t; - t_d.construct(x_d + y_d); - t.construct(x + y); + t_d.construct_from([&]() -> typename CPP2_TYPEOF(t_d)::value_type { return typename CPP2_TYPEOF(t_d)::value_type{x_d + y_d}; }); + t.construct_from([&]() -> typename CPP2_TYPEOF(t)::value_type { return typename CPP2_TYPEOF(t)::value_type{x + y}; }); r_d = cpp2::move(t_d.value()); r = cpp2::move(t.value()); return { std::move(r), std::move(r_d) }; diff --git a/regression-tests/test-results/pure2-autodiff.cpp b/regression-tests/test-results/pure2-autodiff.cpp index 02c385c88..393ef84c9 100644 --- a/regression-tests/test-results/pure2-autodiff.cpp +++ b/regression-tests/test-results/pure2-autodiff.cpp @@ -566,7 +566,7 @@ namespace ad_name { [[nodiscard]] auto func_outer(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_ret{ cpp2::impl::deferred_init ret; #line 4 "pure2-autodiff.cpp2" - ret.construct(x + y); + ret.construct_from([&]() -> typename CPP2_TYPEOF(ret)::value_type { return typename CPP2_TYPEOF(ret)::value_type{x + y}; }); return std::move(ret.value()); } #line 10 "pure2-autodiff.cpp2" @@ -593,133 +593,133 @@ return std::move(ret.value()); } [[nodiscard]] auto ad_test::add_1(cpp2::impl::in x, cpp2::impl::in y) -> add_1_ret{ cpp2::impl::deferred_init r; #line 18 "pure2-autodiff.cpp2" - r.construct(x + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y}; }); return std::move(r.value()); } #line 21 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::add_2(cpp2::impl::in x, cpp2::impl::in y) -> add_2_ret{ cpp2::impl::deferred_init r; #line 22 "pure2-autodiff.cpp2" - r.construct(x + y + x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y + x}; }); return std::move(r.value()); } #line 25 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::sub_1(cpp2::impl::in x, cpp2::impl::in y) -> sub_1_ret{ cpp2::impl::deferred_init r; #line 26 "pure2-autodiff.cpp2" - r.construct(x - y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x - y}; }); return std::move(r.value()); } #line 29 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::sub_2(cpp2::impl::in x, cpp2::impl::in y) -> sub_2_ret{ cpp2::impl::deferred_init r; #line 30 "pure2-autodiff.cpp2" - r.construct(x - y - x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x - y - x}; }); return std::move(r.value()); } #line 33 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::add_sub_2(cpp2::impl::in x, cpp2::impl::in y) -> add_sub_2_ret{ cpp2::impl::deferred_init r; #line 34 "pure2-autodiff.cpp2" - r.construct(x + y - x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y - x}; }); return std::move(r.value()); } #line 37 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::mul_1(cpp2::impl::in x, cpp2::impl::in y) -> mul_1_ret{ cpp2::impl::deferred_init r; #line 38 "pure2-autodiff.cpp2" - r.construct(x * y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * y}; }); return std::move(r.value()); } #line 41 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::mul_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_2_ret{ cpp2::impl::deferred_init r; #line 42 "pure2-autodiff.cpp2" - r.construct(x * y * x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * y * x}; }); return std::move(r.value()); } #line 45 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::div_1(cpp2::impl::in x, cpp2::impl::in y) -> div_1_ret{ cpp2::impl::deferred_init r; #line 46 "pure2-autodiff.cpp2" - r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)}; }); return std::move(r.value()); } #line 49 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::div_2(cpp2::impl::in x, cpp2::impl::in y) -> div_2_ret{ cpp2::impl::deferred_init r; #line 50 "pure2-autodiff.cpp2" - r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),y)}; }); return std::move(r.value()); } #line 53 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::mul_div_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_div_2_ret{ cpp2::impl::deferred_init r; #line 54 "pure2-autodiff.cpp2" - r.construct(x * y / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),x)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * y / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),x)}; }); return std::move(r.value()); } #line 57 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::mul_add(cpp2::impl::in x, cpp2::impl::in y) -> mul_add_ret{ cpp2::impl::deferred_init r; #line 58 "pure2-autodiff.cpp2" - r.construct(x * (x + y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * (x + y)}; }); return std::move(r.value()); } #line 61 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::add_mul(cpp2::impl::in x, cpp2::impl::in y) -> add_mul_ret{ cpp2::impl::deferred_init r; #line 62 "pure2-autodiff.cpp2" - r.construct(x + x * y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + x * y}; }); return std::move(r.value()); } #line 65 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::prefix_add(cpp2::impl::in x, cpp2::impl::in y) -> prefix_add_ret{ cpp2::impl::deferred_init r; #line 66 "pure2-autodiff.cpp2" - r.construct(+x + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{+x + y}; }); return std::move(r.value()); } #line 69 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::prefix_sub(cpp2::impl::in x, cpp2::impl::in y) -> prefix_sub_ret{ cpp2::impl::deferred_init r; #line 70 "pure2-autodiff.cpp2" - r.construct(-x + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{-x + y}; }); return std::move(r.value()); } #line 73 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::func(cpp2::impl::in x, cpp2::impl::in y) -> func_ret{ cpp2::impl::deferred_init ret; #line 74 "pure2-autodiff.cpp2" - ret.construct(x + y); + ret.construct_from([&]() -> typename CPP2_TYPEOF(ret)::value_type { return typename CPP2_TYPEOF(ret)::value_type{x + y}; }); return std::move(ret.value()); } #line 77 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::func_call(cpp2::impl::in x, cpp2::impl::in y) -> func_call_ret{ cpp2::impl::deferred_init r; #line 78 "pure2-autodiff.cpp2" - r.construct(x * func(x, y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * func(x, y)}; }); return std::move(r.value()); } #line 81 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::func_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_call_ret{ cpp2::impl::deferred_init r; #line 82 "pure2-autodiff.cpp2" - r.construct(x * func_outer(x, y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * func_outer(x, y)}; }); return std::move(r.value()); } #line 85 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::sin_call(cpp2::impl::in x, cpp2::impl::in y) -> sin_call_ret{ cpp2::impl::deferred_init r; #line 86 "pure2-autodiff.cpp2" - r.construct(sin(x - y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{sin(x - y)}; }); return std::move(r.value()); } #line 89 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::if_branch(cpp2::impl::in x, cpp2::impl::in y) -> if_branch_ret{ cpp2::impl::deferred_init r; #line 90 "pure2-autodiff.cpp2" - r.construct(x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x}; }); if (cpp2::impl::cmp_less(x,0.0)) { r.value() = y; @@ -731,10 +731,10 @@ return std::move(ret.value()); } cpp2::impl::deferred_init r; #line 98 "pure2-autodiff.cpp2" if (cpp2::impl::cmp_less(x,0.0)) { - r.construct(y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{y}; }); } else { - r.construct(x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x}; }); }return std::move(r.value()); } @@ -749,7 +749,7 @@ return std::move(ret.value()); } #line 111 "pure2-autodiff.cpp2" double t {x + y}; - r.construct(cpp2::move(t)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t)}; }); return std::move(r.value()); } #line 116 "pure2-autodiff.cpp2" @@ -757,7 +757,7 @@ return std::move(ret.value()); } cpp2::impl::deferred_init r; #line 117 "pure2-autodiff.cpp2" int i {}; - r.construct(x + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y}; }); i = 2; static_cast(cpp2::move(i)); @@ -770,7 +770,7 @@ return std::move(ret.value()); } auto t {0.0}; t = x + y; - r.construct(cpp2::move(t)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t)}; }); return std::move(r.value()); } #line 131 "pure2-autodiff.cpp2" @@ -780,7 +780,7 @@ return std::move(ret.value()); } double t {}; t = x + y; - r.construct(cpp2::move(t)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t)}; }); return std::move(r.value()); } #line 138 "pure2-autodiff.cpp2" @@ -788,16 +788,16 @@ return std::move(ret.value()); } cpp2::impl::deferred_init r; #line 139 "pure2-autodiff.cpp2" cpp2::impl::deferred_init t; - t.construct(x + y); + t.construct_from([&]() -> typename CPP2_TYPEOF(t)::value_type { return typename CPP2_TYPEOF(t)::value_type{x + y}; }); - r.construct(cpp2::move(t.value())); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t.value())}; }); return std::move(r.value()); } #line 145 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test::while_loop(cpp2::impl::in x, cpp2::impl::in y) -> while_loop_ret{ cpp2::impl::deferred_init r; #line 146 "pure2-autodiff.cpp2" - r.construct(x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x}; }); { int i{0}; double t{0.0}; @@ -818,7 +818,7 @@ double t{0.0}; [[nodiscard]] auto ad_test::do_while_loop(cpp2::impl::in x, cpp2::impl::in y) -> do_while_loop_ret{ cpp2::impl::deferred_init r; #line 156 "pure2-autodiff.cpp2" - r.construct(x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x}; }); { auto i{0}; @@ -844,7 +844,7 @@ auto i{0}; CPP2_UFCS(push_back)(v, x); CPP2_UFCS(push_back)(v, y); - r.construct(0.0); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{0.0}; }); for ( auto const& t : cpp2::move(v) ) { @@ -859,7 +859,7 @@ auto i{0}; type_outer t {}; t.a = x; - r.construct(cpp2::move(t).a + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t).a + y}; }); return std::move(r.value()); } #line 187 "pure2-autodiff.cpp2" @@ -869,7 +869,7 @@ auto i{0}; type_outer t {}; t.a = x; - r.construct(CPP2_UFCS(add)(cpp2::move(t), y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{CPP2_UFCS(add)(cpp2::move(t), y)}; }); return std::move(r.value()); } [[nodiscard]] auto ad_test::add_1_d(cpp2::impl::in x, cpp2::impl::in x_d, cpp2::impl::in y, cpp2::impl::in y_d) -> add_1_d_ret{ @@ -1128,8 +1128,8 @@ double t_d {}; cpp2::impl::deferred_init t_d; cpp2::impl::deferred_init t; - t_d.construct(x_d + y_d); - t.construct(x + y); + t_d.construct_from([&]() -> typename CPP2_TYPEOF(t_d)::value_type { return typename CPP2_TYPEOF(t_d)::value_type{x_d + y_d}; }); + t.construct_from([&]() -> typename CPP2_TYPEOF(t)::value_type { return typename CPP2_TYPEOF(t)::value_type{x + y}; }); r_d = cpp2::move(t_d.value()); r = cpp2::move(t.value()); return { std::move(r), std::move(r_d) }; @@ -1243,112 +1243,112 @@ type_outer_d t_d {}; [[nodiscard]] auto ad_test_reverse::add_1(cpp2::impl::in x, cpp2::impl::in y) -> add_1_ret{ cpp2::impl::deferred_init r; #line 198 "pure2-autodiff.cpp2" - r.construct(x + y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y}; }); return std::move(r.value()); } #line 201 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::add_2(cpp2::impl::in x, cpp2::impl::in y) -> add_2_ret{ cpp2::impl::deferred_init r; #line 202 "pure2-autodiff.cpp2" - r.construct(x + y + x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y + x}; }); return std::move(r.value()); } #line 205 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::sub_1(cpp2::impl::in x, cpp2::impl::in y) -> sub_1_ret{ cpp2::impl::deferred_init r; #line 206 "pure2-autodiff.cpp2" - r.construct(x - y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x - y}; }); return std::move(r.value()); } #line 209 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::sub_2(cpp2::impl::in x, cpp2::impl::in y) -> sub_2_ret{ cpp2::impl::deferred_init r; #line 210 "pure2-autodiff.cpp2" - r.construct(x - y - x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x - y - x}; }); return std::move(r.value()); } #line 213 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::add_sub_2(cpp2::impl::in x, cpp2::impl::in y) -> add_sub_2_ret{ cpp2::impl::deferred_init r; #line 214 "pure2-autodiff.cpp2" - r.construct(x + y - x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + y - x}; }); return std::move(r.value()); } #line 217 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::mul_1(cpp2::impl::in x, cpp2::impl::in y) -> mul_1_ret{ cpp2::impl::deferred_init r; #line 218 "pure2-autodiff.cpp2" - r.construct(x * y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * y}; }); return std::move(r.value()); } #line 221 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::mul_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_2_ret{ cpp2::impl::deferred_init r; #line 222 "pure2-autodiff.cpp2" - r.construct(x * y * x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * y * x}; }); return std::move(r.value()); } #line 225 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::div_1(cpp2::impl::in x, cpp2::impl::in y) -> div_1_ret{ cpp2::impl::deferred_init r; #line 226 "pure2-autodiff.cpp2" - r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y)}; }); return std::move(r.value()); } #line 229 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::div_2(cpp2::impl::in x, cpp2::impl::in y) -> div_2_ret{ cpp2::impl::deferred_init r; #line 230 "pure2-autodiff.cpp2" - r.construct(x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(x),y) / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),y)}; }); return std::move(r.value()); } #line 233 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::mul_div_2(cpp2::impl::in x, cpp2::impl::in y) -> mul_div_2_ret{ cpp2::impl::deferred_init r; #line 234 "pure2-autodiff.cpp2" - r.construct(x * y / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),x)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * y / CPP2_ASSERT_NOT_ZERO(CPP2_TYPEOF(y),x)}; }); return std::move(r.value()); } #line 237 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::mul_add(cpp2::impl::in x, cpp2::impl::in y) -> mul_add_ret{ cpp2::impl::deferred_init r; #line 238 "pure2-autodiff.cpp2" - r.construct(x * (x + y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * (x + y)}; }); return std::move(r.value()); } #line 241 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::add_mul(cpp2::impl::in x, cpp2::impl::in y) -> add_mul_ret{ cpp2::impl::deferred_init r; #line 242 "pure2-autodiff.cpp2" - r.construct(x + x * y); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x + x * y}; }); return std::move(r.value()); } #line 245 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::sin_call(cpp2::impl::in x, cpp2::impl::in y) -> sin_call_ret{ cpp2::impl::deferred_init r; #line 246 "pure2-autodiff.cpp2" - r.construct(sin(x - y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{sin(x - y)}; }); return std::move(r.value()); } #line 249 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::func(cpp2::impl::in x, cpp2::impl::in y) -> func_ret{ cpp2::impl::deferred_init ret; #line 250 "pure2-autodiff.cpp2" - ret.construct(x + y); + ret.construct_from([&]() -> typename CPP2_TYPEOF(ret)::value_type { return typename CPP2_TYPEOF(ret)::value_type{x + y}; }); return std::move(ret.value()); } #line 253 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::func_call(cpp2::impl::in x, cpp2::impl::in y) -> func_call_ret{ cpp2::impl::deferred_init r; #line 254 "pure2-autodiff.cpp2" - r.construct(x * func(x, y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * func(x, y)}; }); return std::move(r.value()); } #line 257 "pure2-autodiff.cpp2" [[nodiscard]] auto ad_test_reverse::func_outer_call(cpp2::impl::in x, cpp2::impl::in y) -> func_outer_call_ret{ cpp2::impl::deferred_init r; #line 258 "pure2-autodiff.cpp2" - r.construct(x * func_outer(x, y)); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * func_outer(x, y)}; }); return std::move(r.value()); } [[nodiscard]] auto ad_test_reverse::add_1_b(cpp2::impl::in x, double& x_b, cpp2::impl::in y, double& y_b, double& r_b) -> add_1_b_ret{ @@ -1526,7 +1526,7 @@ double temp_2_b {0.0}; [[nodiscard]] auto ad_test_twice::mul_1(cpp2::impl::in x) -> mul_1_ret{ cpp2::impl::deferred_init r; #line 265 "pure2-autodiff.cpp2" - r.construct(x * x); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{x * x}; }); return std::move(r.value()); } [[nodiscard]] auto ad_test_twice::mul_1_d(cpp2::impl::in x, cpp2::impl::in x_d) -> mul_1_d_ret{ @@ -1581,15 +1581,15 @@ auto write_output_reverse(cpp2::impl::in func, cpp2::impl::in typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{x * x}; }); } else {if (cpp2::impl::cmp_less(x,3)) { - y.construct(x + sin(x) + 10); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{x + sin(x) + 10}; }); } else { - y.construct(sin(x) * x * x); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{sin(x) * x * x}; }); }}return std::move(y.value()); } diff --git a/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp new file mode 100644 index 000000000..464e5fa07 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp @@ -0,0 +1,60 @@ + +#define CPP2_INCLUDE_STD Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2" + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2" +cpp2::i32 inline constexpr value{ 20 }; +#line 2 "pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2" + +[[nodiscard]] constexpr auto foo() -> cpp2::i32; + +[[nodiscard]] constexpr auto add(cpp2::impl::in x, cpp2::impl::in y) -> cpp2::i32; + +[[nodiscard]] auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2" + +#line 3 "pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2" +[[nodiscard]] constexpr auto foo() -> cpp2::i32 { return 20; } + +#line 5 "pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2" +[[nodiscard]] constexpr auto add(cpp2::impl::in x, cpp2::impl::in y) -> cpp2::i32 { return x + y; } + +#line 7 "pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2" +[[nodiscard]] auto main() -> int{ + cpp2::i8 a0 {value + 100}; + cpp2::impl::deferred_init a; + a.construct_from([&]() -> typename CPP2_TYPEOF(a)::value_type { return typename CPP2_TYPEOF(a)::value_type{value + 100}; }); + + cpp2::i8 b0 {foo() + 100}; + cpp2::impl::deferred_init b; + b.construct_from([&]() -> typename CPP2_TYPEOF(b)::value_type { return typename CPP2_TYPEOF(b)::value_type{foo() + 100}; }); + + cpp2::i16 c0 {add(value, foo()) + 100}; + cpp2::impl::deferred_init c; + c.construct_from([&]() -> typename CPP2_TYPEOF(c)::value_type { return typename CPP2_TYPEOF(c)::value_type{add(value, foo()) + 100}; }); + + cpp2::i32 constexpr local{ 10 }; + + cpp2::i16 d0 {add(local, foo()) * 2 + value}; + cpp2::impl::deferred_init d; + d.construct_from([&]() -> typename CPP2_TYPEOF(d)::value_type { return typename CPP2_TYPEOF(d)::value_type{add(local, foo()) * 2 + value}; }); + + std::array e0 {value + 100, foo() + 100, add(local, foo())}; + cpp2::impl::deferred_init> e; + e.construct_from([&]() -> typename CPP2_TYPEOF(e)::value_type { return typename CPP2_TYPEOF(e)::value_type{value + 100, foo() + 100, add(local, foo())}; }); + + return 0; +} + diff --git a/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2.output new file mode 100644 index 000000000..032039e31 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-deferred-init-narrowing-constexpr.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-literals.cpp b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-literals.cpp new file mode 100644 index 000000000..f599fdde1 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-literals.cpp @@ -0,0 +1,48 @@ + +#define CPP2_INCLUDE_STD Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-literals.cpp2" + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-literals.cpp2" +[[nodiscard]] auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-literals.cpp2" +[[nodiscard]] auto main() -> int{ +#line 2 "pure2-bugfix-for-deferred-init-narrowing-literals.cpp2" + cpp2::u8 a0 {'a'}; + cpp2::impl::deferred_init a; + a.construct_from([&]() -> typename CPP2_TYPEOF(a)::value_type { return typename CPP2_TYPEOF(a)::value_type{'a'}; }); + + cpp2::i8 b0 {1}; + cpp2::impl::deferred_init b; + b.construct_from([&]() -> typename CPP2_TYPEOF(b)::value_type { return typename CPP2_TYPEOF(b)::value_type{1}; }); + + cpp2::u8 c0 {2}; + cpp2::impl::deferred_init c; + c.construct_from([&]() -> typename CPP2_TYPEOF(c)::value_type { return typename CPP2_TYPEOF(c)::value_type{2}; }); + + cpp2::i16 d0 {3}; + cpp2::impl::deferred_init d; + d.construct_from([&]() -> typename CPP2_TYPEOF(d)::value_type { return typename CPP2_TYPEOF(d)::value_type{3}; }); + + cpp2::u16 e0 {4}; + cpp2::impl::deferred_init e; + e.construct_from([&]() -> typename CPP2_TYPEOF(e)::value_type { return typename CPP2_TYPEOF(e)::value_type{4}; }); + + std::array f0 {5, 6, 7}; + cpp2::impl::deferred_init> f; + f.construct_from([&]() -> typename CPP2_TYPEOF(f)::value_type { return typename CPP2_TYPEOF(f)::value_type{5, 6, 7}; }); + + return 0; +} + diff --git a/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-literals.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-literals.cpp2.output new file mode 100644 index 000000000..88b4b1f98 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-literals.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-deferred-init-narrowing-literals.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp new file mode 100644 index 000000000..8b435e9df --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp @@ -0,0 +1,81 @@ + +#define CPP2_INCLUDE_STD Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2" + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2" +// Target type is {i8, i8}. We try every pair from: +// ce_i8, ce_i16, rt_i8, rt_i16 +// = 4 x 4 = 16 combinations. +// +// Constexpr sources must appear by name in the initializer, otherwise they +// stop being constant expressions and every i16 case would fail. + +#line 8 "pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2" +cpp2::i8 inline constexpr ce_i8{ 8 }; +cpp2::i16 inline constexpr ce_i16{ 8 }; + +auto try_all_combinations(cpp2::impl::in rt_i8, cpp2::impl::in rt_i16) -> void; + +#line 49 "pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2" +[[nodiscard]] auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2" + +#line 11 "pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2" +auto try_all_combinations(cpp2::impl::in rt_i8, cpp2::impl::in rt_i16) -> void{ + cpp2::impl::deferred_init> a00; + a00.construct_from([&]() -> typename CPP2_TYPEOF(a00)::value_type { return typename CPP2_TYPEOF(a00)::value_type{ce_i8, ce_i8}; }); + cpp2::impl::deferred_init> a01; + a01.construct_from([&]() -> typename CPP2_TYPEOF(a01)::value_type { return typename CPP2_TYPEOF(a01)::value_type{ce_i8, ce_i16}; }); + cpp2::impl::deferred_init> a02; + a02.construct_from([&]() -> typename CPP2_TYPEOF(a02)::value_type { return typename CPP2_TYPEOF(a02)::value_type{ce_i8, rt_i8}; }); + cpp2::impl::deferred_init> a03; + a03.construct_from([&]() -> typename CPP2_TYPEOF(a03)::value_type { return typename CPP2_TYPEOF(a03)::value_type{ce_i8, rt_i16}; });// fail: runtime i16 -> i8 + + cpp2::impl::deferred_init> a10; + a10.construct_from([&]() -> typename CPP2_TYPEOF(a10)::value_type { return typename CPP2_TYPEOF(a10)::value_type{ce_i16, ce_i8}; }); + cpp2::impl::deferred_init> a11; + a11.construct_from([&]() -> typename CPP2_TYPEOF(a11)::value_type { return typename CPP2_TYPEOF(a11)::value_type{ce_i16, ce_i16}; }); + cpp2::impl::deferred_init> a12; + a12.construct_from([&]() -> typename CPP2_TYPEOF(a12)::value_type { return typename CPP2_TYPEOF(a12)::value_type{ce_i16, rt_i8}; }); + cpp2::impl::deferred_init> a13; + a13.construct_from([&]() -> typename CPP2_TYPEOF(a13)::value_type { return typename CPP2_TYPEOF(a13)::value_type{ce_i16, rt_i16}; });// fail: runtime i16 -> i8 + + cpp2::impl::deferred_init> a20; + a20.construct_from([&]() -> typename CPP2_TYPEOF(a20)::value_type { return typename CPP2_TYPEOF(a20)::value_type{rt_i8, ce_i8}; }); + cpp2::impl::deferred_init> a21; + a21.construct_from([&]() -> typename CPP2_TYPEOF(a21)::value_type { return typename CPP2_TYPEOF(a21)::value_type{rt_i8, ce_i16}; }); + cpp2::impl::deferred_init> a22; + a22.construct_from([&]() -> typename CPP2_TYPEOF(a22)::value_type { return typename CPP2_TYPEOF(a22)::value_type{rt_i8, rt_i8}; }); + cpp2::impl::deferred_init> a23; + a23.construct_from([&]() -> typename CPP2_TYPEOF(a23)::value_type { return typename CPP2_TYPEOF(a23)::value_type{rt_i8, rt_i16}; });// fail: runtime i16 -> i8 + + cpp2::impl::deferred_init> a30; + a30.construct_from([&]() -> typename CPP2_TYPEOF(a30)::value_type { return typename CPP2_TYPEOF(a30)::value_type{rt_i16, ce_i8}; });// fail: runtime i16 -> i8 + cpp2::impl::deferred_init> a31; + a31.construct_from([&]() -> typename CPP2_TYPEOF(a31)::value_type { return typename CPP2_TYPEOF(a31)::value_type{rt_i16, ce_i16}; });// fail: runtime i16 -> i8 + cpp2::impl::deferred_init> a32; + a32.construct_from([&]() -> typename CPP2_TYPEOF(a32)::value_type { return typename CPP2_TYPEOF(a32)::value_type{rt_i16, rt_i8}; });// fail: runtime i16 -> i8 + cpp2::impl::deferred_init> a33; + a33.construct_from([&]() -> typename CPP2_TYPEOF(a33)::value_type { return typename CPP2_TYPEOF(a33)::value_type{rt_i16, rt_i16}; });// fail: runtime i16 -> i8 +} + +#line 49 "pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2" +[[nodiscard]] auto main() -> int{ + cpp2::i8 rt_i8 {8}; + cpp2::i16 rt_i16 {8}; + try_all_combinations(cpp2::move(rt_i8), cpp2::move(rt_i16)); + return 0; +} + diff --git a/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2.output new file mode 100644 index 000000000..752694f69 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-deferred-init-narrowing-matrix-error.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp new file mode 100644 index 000000000..9bc3fc1e8 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp @@ -0,0 +1,36 @@ + +#define CPP2_INCLUDE_STD Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2" + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2" +[[nodiscard]] auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2" +[[nodiscard]] auto main() -> int{ +#line 2 "pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2" + cpp2::i8 a0 {-1}; + cpp2::impl::deferred_init a; + a.construct_from([&]() -> typename CPP2_TYPEOF(a)::value_type { return typename CPP2_TYPEOF(a)::value_type{-1}; }); + + cpp2::i16 b0 {-2}; + cpp2::impl::deferred_init b; + b.construct_from([&]() -> typename CPP2_TYPEOF(b)::value_type { return typename CPP2_TYPEOF(b)::value_type{-2}; }); + + std::array c0 {-3, -4, -5}; + cpp2::impl::deferred_init> c; + c.construct_from([&]() -> typename CPP2_TYPEOF(c)::value_type { return typename CPP2_TYPEOF(c)::value_type{-3, -4, -5}; }); + + return 0; +} + diff --git a/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2.output new file mode 100644 index 000000000..7fbf3df56 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-deferred-init-narrowing-negative-literals.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/test-results/pure2-bugfix-for-name-lookup-and-value-decoration.cpp b/regression-tests/test-results/pure2-bugfix-for-name-lookup-and-value-decoration.cpp index 58b5d88cb..4f9e7713a 100644 --- a/regression-tests/test-results/pure2-bugfix-for-name-lookup-and-value-decoration.cpp +++ b/regression-tests/test-results/pure2-bugfix-for-name-lookup-and-value-decoration.cpp @@ -25,7 +25,7 @@ using vals_ret = int; [[nodiscard]] auto vals() -> vals_ret{ cpp2::impl::deferred_init i; #line 2 "pure2-bugfix-for-name-lookup-and-value-decoration.cpp2" - i.construct(42); + i.construct_from([&]() -> typename CPP2_TYPEOF(i)::value_type { return typename CPP2_TYPEOF(i)::value_type{42}; }); return std::move(i.value()); } diff --git a/regression-tests/test-results/pure2-function-body-reflection.cpp b/regression-tests/test-results/pure2-function-body-reflection.cpp index 0fc93b2e5..ca0b1ce17 100644 --- a/regression-tests/test-results/pure2-function-body-reflection.cpp +++ b/regression-tests/test-results/pure2-function-body-reflection.cpp @@ -98,9 +98,9 @@ auto sample_function_before_type() -> void{} cpp2::impl::deferred_init s; cpp2::impl::deferred_init t; #line 14 "pure2-function-body-reflection.cpp2" - r.construct(42.0); - s.construct(2.71828f); - t.construct("e times pi"); + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{42.0}; }); + s.construct_from([&]() -> typename CPP2_TYPEOF(s)::value_type { return typename CPP2_TYPEOF(s)::value_type{2.71828f}; }); + t.construct_from([&]() -> typename CPP2_TYPEOF(t)::value_type { return typename CPP2_TYPEOF(t)::value_type{"e times pi"}; }); return { std::move(r.value()), std::move(s.value()), std::move(t.value()) }; } #line 19 "pure2-function-body-reflection.cpp2" diff --git a/regression-tests/test-results/pure2-function-typeids.cpp b/regression-tests/test-results/pure2-function-typeids.cpp index fb07eb976..ae37bcc6c 100644 --- a/regression-tests/test-results/pure2-function-typeids.cpp +++ b/regression-tests/test-results/pure2-function-typeids.cpp @@ -50,7 +50,7 @@ auto g_in( cpp2::impl::in s) -> void{std::cout << "Come in, " #line 7 "pure2-function-typeids.cpp2" auto g_inout(std::string& s) -> void{std::cout << "Come in awhile, but take some biscuits on your way out, " + cpp2::to_string(s) + "!\n"; } #line 8 "pure2-function-typeids.cpp2" -auto g_out(cpp2::impl::out s) -> void{s.construct("A Powerful Mage");} +auto g_out(cpp2::impl::out s) -> void{s.construct_from([&]() -> typename CPP2_TYPEOF(s)::value_type { return typename CPP2_TYPEOF(s)::value_type{"A Powerful Mage"}; });} #line 9 "pure2-function-typeids.cpp2" auto g_move(std::string&& s) -> void{std::cout << "I hear you've moving, " + cpp2::to_string(cpp2::move(s)) + "?\n";} diff --git a/regression-tests/test-results/pure2-initialization-safety-with-else-if.cpp b/regression-tests/test-results/pure2-initialization-safety-with-else-if.cpp index b612de40e..cea336692 100644 --- a/regression-tests/test-results/pure2-initialization-safety-with-else-if.cpp +++ b/regression-tests/test-results/pure2-initialization-safety-with-else-if.cpp @@ -47,18 +47,18 @@ auto main(int const argc_, char** argv_) -> int{ auto d {4}; if (CPP2_UFCS(size)(args) == 3) { - p.construct(&a); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{&a}; }); }else {if (true) { if (CPP2_UFCS(size)(args) == 2) { - p.construct(&c); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{&c}; }); }else {if (cpp2::impl::cmp_greater(cpp2::move(b),0)) { - p.construct(&a); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{&a}; }); } else { - p.construct(&d); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{&d}; }); }} }else { - p.construct(&c); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{&c}; }); }} std::cout << *cpp2::impl::assert_not_null(cpp2::move(p.value())) << std::endl; @@ -69,22 +69,22 @@ auto main(int const argc_, char** argv_) -> int{ cpp2::impl::deferred_init r; #line 29 "pure2-initialization-safety-with-else-if.cpp2" cpp2::impl::deferred_init t; - t.construct(x + y); + t.construct_from([&]() -> typename CPP2_TYPEOF(t)::value_type { return typename CPP2_TYPEOF(t)::value_type{x + y}; }); - r.construct(cpp2::move(t.value()));// OK, after t but it's a return value + r.construct_from([&]() -> typename CPP2_TYPEOF(r)::value_type { return typename CPP2_TYPEOF(r)::value_type{cpp2::move(t.value())}; });// OK, after t but it's a return value return std::move(r.value()); } #line 36 "pure2-initialization-safety-with-else-if.cpp2" auto ok() -> void{ cpp2::impl::deferred_init i; if (true) { - i.construct(42); + i.construct_from([&]() -> typename CPP2_TYPEOF(i)::value_type { return typename CPP2_TYPEOF(i)::value_type{42}; }); while( true ) { // OK: in-branch loop is after initialization i.value() = 42; } } else { - i.construct(42); + i.construct_from([&]() -> typename CPP2_TYPEOF(i)::value_type { return typename CPP2_TYPEOF(i)::value_type{42}; }); } i.value() = 42; } diff --git a/regression-tests/test-results/pure2-last-use.cpp b/regression-tests/test-results/pure2-last-use.cpp index f08a06d70..e7ae3150b 100644 --- a/regression-tests/test-results/pure2-last-use.cpp +++ b/regression-tests/test-results/pure2-last-use.cpp @@ -656,7 +656,7 @@ auto issue_683(auto const& args) -> void{ } cpp2::impl::deferred_init n; - n.construct(0); + n.construct_from([&]() -> typename CPP2_TYPEOF(n)::value_type { return typename CPP2_TYPEOF(n)::value_type{0}; }); } #line 114 "pure2-last-use.cpp2" @@ -1298,7 +1298,7 @@ auto draw() -> void{ auto enum_0() -> void{ cpp2::impl::deferred_init underlying_type; if (true) {} - underlying_type.construct(""); + underlying_type.construct_from([&]() -> typename CPP2_TYPEOF(underlying_type)::value_type { return typename CPP2_TYPEOF(underlying_type)::value_type{""}; }); } #line 799 "pure2-last-use.cpp2" auto enum_1() -> void{ @@ -1362,14 +1362,14 @@ return ret; } #line 853 "pure2-last-use.cpp2" auto deferred_non_copyable_0() -> void{ cpp2::impl::deferred_init> p; - p.construct(); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{}; }); f_copy(std::move(cpp2::move(p.value()))); } #line 859 "pure2-last-use.cpp2" [[nodiscard]] auto deferred_non_copyable_1() -> auto{ cpp2::impl::deferred_init> p; - p.construct(); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{}; }); return std::move(cpp2::move(p.value())); } @@ -1377,7 +1377,7 @@ auto deferred_non_copyable_0() -> void{ [[nodiscard]] auto deferred_non_copyable_2() -> deferred_non_copyable_2_ret{ cpp2::impl::deferred_init> p; #line 866 "pure2-last-use.cpp2" - p.construct(); + p.construct_from([&]() -> typename CPP2_TYPEOF(p)::value_type { return typename CPP2_TYPEOF(p)::value_type{}; }); return std::move(p.value()); } #line 869 "pure2-last-use.cpp2" diff --git a/regression-tests/test-results/pure2-look-up-parameter-across-unnamed-function.cpp b/regression-tests/test-results/pure2-look-up-parameter-across-unnamed-function.cpp index a2d442297..a18c677b5 100644 --- a/regression-tests/test-results/pure2-look-up-parameter-across-unnamed-function.cpp +++ b/regression-tests/test-results/pure2-look-up-parameter-across-unnamed-function.cpp @@ -43,7 +43,7 @@ using g_ret = int; [[nodiscard]] auto g() -> g_ret{ cpp2::impl::deferred_init ri; #line 10 "pure2-look-up-parameter-across-unnamed-function.cpp2" - ri.construct(0); + ri.construct_from([&]() -> typename CPP2_TYPEOF(ri)::value_type { return typename CPP2_TYPEOF(ri)::value_type{0}; }); auto pred {[](auto const& e) -> decltype(auto) { return e == 1; }}; ri.value() = 42; cpp2::move(pred)(ri.value()); diff --git a/regression-tests/test-results/pure2-print.cpp b/regression-tests/test-results/pure2-print.cpp index dd93d0504..eea28f9f7 100644 --- a/regression-tests/test-results/pure2-print.cpp +++ b/regression-tests/test-results/pure2-print.cpp @@ -161,8 +161,8 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias{ 42 }; cpp2::impl::deferred_init offset; cpp2::impl::deferred_init name; #line 57 "pure2-print.cpp2" - offset.construct(53); - name.construct("plugh"); + offset.construct_from([&]() -> typename CPP2_TYPEOF(offset)::value_type { return typename CPP2_TYPEOF(offset)::value_type{53}; }); + name.construct_from([&]() -> typename CPP2_TYPEOF(name)::value_type { return typename CPP2_TYPEOF(name)::value_type{"plugh"}; }); return { std::move(offset.value()), std::move(name.value()) }; } #line 61 "pure2-print.cpp2" diff --git a/regression-tests/test-results/pure2-return-tuple-operator.cpp b/regression-tests/test-results/pure2-return-tuple-operator.cpp index 4c4aca902..d8df3f13d 100644 --- a/regression-tests/test-results/pure2-return-tuple-operator.cpp +++ b/regression-tests/test-results/pure2-return-tuple-operator.cpp @@ -55,8 +55,8 @@ auto main() -> int; cpp2::impl::deferred_init x; cpp2::impl::deferred_init y; #line 4 "pure2-return-tuple-operator.cpp2" - x.construct(12); - y.construct(34); + x.construct_from([&]() -> typename CPP2_TYPEOF(x)::value_type { return typename CPP2_TYPEOF(x)::value_type{12}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{34}; }); return { std::move(x.value()), std::move(y.value()) }; } #line 8 "pure2-return-tuple-operator.cpp2" @@ -64,8 +64,8 @@ auto main() -> int; cpp2::impl::deferred_init x; cpp2::impl::deferred_init y; #line 9 "pure2-return-tuple-operator.cpp2" - x.construct(23); - y.construct(45); + x.construct_from([&]() -> typename CPP2_TYPEOF(x)::value_type { return typename CPP2_TYPEOF(x)::value_type{23}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{45}; }); return { std::move(x.value()), std::move(y.value()) }; } #line 13 "pure2-return-tuple-operator.cpp2" @@ -73,8 +73,8 @@ auto main() -> int; cpp2::impl::deferred_init x; cpp2::impl::deferred_init y; #line 14 "pure2-return-tuple-operator.cpp2" - x.construct(34 * (idx + 1)); - y.construct(56 * (idx + 1)); + x.construct_from([&]() -> typename CPP2_TYPEOF(x)::value_type { return typename CPP2_TYPEOF(x)::value_type{34 * (idx + 1)}; }); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{56 * (idx + 1)}; }); return { std::move(x.value()), std::move(y.value()) }; } diff --git a/regression-tests/test-results/pure2-trailing-commas.cpp b/regression-tests/test-results/pure2-trailing-commas.cpp index acaf2189c..02ce12770 100644 --- a/regression-tests/test-results/pure2-trailing-commas.cpp +++ b/regression-tests/test-results/pure2-trailing-commas.cpp @@ -50,7 +50,7 @@ template [[nodiscard]] auto g(T const& a, U const& b) -> [[nodiscard]] auto doubler(cpp2::impl::in a) -> doubler_ret{ cpp2::impl::deferred_init i; #line 6 "pure2-trailing-commas.cpp2" - i.construct(a * 2); + i.construct_from([&]() -> typename CPP2_TYPEOF(i)::value_type { return typename CPP2_TYPEOF(i)::value_type{a * 2}; }); return std::move(i.value()); } vals::vals(auto&& i_) diff --git a/regression-tests/test-results/pure2-type-safety-1.cpp b/regression-tests/test-results/pure2-type-safety-1.cpp index 9dc0491ab..74fe926d0 100644 --- a/regression-tests/test-results/pure2-type-safety-1.cpp +++ b/regression-tests/test-results/pure2-type-safety-1.cpp @@ -113,8 +113,8 @@ auto test_1365(auto const& o) -> void{ #line 63 "pure2-type-safety-1.cpp2" auto print(cpp2::impl::in msg, cpp2::impl::in b) -> void{ cpp2::impl::deferred_init bmsg; - if (b) { bmsg.construct("true");} - else {bmsg.construct("false"); } + if (b) { bmsg.construct_from([&]() -> typename CPP2_TYPEOF(bmsg)::value_type { return typename CPP2_TYPEOF(bmsg)::value_type{"true"}; });} + else {bmsg.construct_from([&]() -> typename CPP2_TYPEOF(bmsg)::value_type { return typename CPP2_TYPEOF(bmsg)::value_type{"false"}; }); } std::cout << std::setw(40) << msg << cpp2::move(bmsg.value()) << "\n"; } diff --git a/regression-tests/test-results/pure2-types-order-independence-and-nesting.cpp b/regression-tests/test-results/pure2-types-order-independence-and-nesting.cpp index d56d88d2e..ffcf09966 100644 --- a/regression-tests/test-results/pure2-types-order-independence-and-nesting.cpp +++ b/regression-tests/test-results/pure2-types-order-independence-and-nesting.cpp @@ -112,7 +112,7 @@ namespace N { #line 10 "pure2-types-order-independence-and-nesting.cpp2" X::X(cpp2::impl::out y) - : py{(y.construct(&(*this)), &y.value() )}{ + : py{(y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{&(*this)}; }), &y.value() )}{ // === The following comments will stay close to, but not exactly at, // the corresponding lines that get moved to the Cpp1 mem-init-list @@ -138,7 +138,7 @@ namespace N { } #line 10 "pure2-types-order-independence-and-nesting.cpp2" auto X::operator=(cpp2::impl::out y) -> X& { - y.construct(&(*this)); + y.construct_from([&]() -> typename CPP2_TYPEOF(y)::value_type { return typename CPP2_TYPEOF(y)::value_type{&(*this)}; }); py = &y.value(); #line 31 "pure2-types-order-independence-and-nesting.cpp2" diff --git a/regression-tests/test-results/pure2-ufcs-member-access-and-chaining.cpp b/regression-tests/test-results/pure2-ufcs-member-access-and-chaining.cpp index effd2b779..0accab9a9 100644 --- a/regression-tests/test-results/pure2-ufcs-member-access-and-chaining.cpp +++ b/regression-tests/test-results/pure2-ufcs-member-access-and-chaining.cpp @@ -89,7 +89,7 @@ auto no_return([[maybe_unused]] auto const& unnamed_param_1) -> void{} [[nodiscard]] auto fun() -> fun_ret{ cpp2::impl::deferred_init i; #line 36 "pure2-ufcs-member-access-and-chaining.cpp2" - i.construct(42); + i.construct_from([&]() -> typename CPP2_TYPEOF(i)::value_type { return typename CPP2_TYPEOF(i)::value_type{42}; }); return std::move(i.value()); } diff --git a/source/to_cpp1.h b/source/to_cpp1.h index 9cc5b669d..37c274703 100644 --- a/source/to_cpp1.h +++ b/source/to_cpp1.h @@ -4112,15 +4112,23 @@ class cppfront // Normally we'll just emit the operator, but if this is an // assignment that's a definite initialization, change it to - // a .construct() call + // a .construct_from() call so brace-init stays in the caller's context if ( x.op->type() == lexeme::Assignment && in_definite_init ) { - printer.print_cpp2( ".construct(", n.position() ); + auto type = + "typename CPP2_TYPEOF(" + + print_to_string(*n.expr->get_postfix_expression_node()->get_first_token_ignoring_this()) + + ")::value_type"; + printer.print_cpp2( + ".construct_from([&]() -> " + type + + " { return " + type + "{", + n.position() + ); emit(*x.expr); - printer.print_cpp2( ")", n.position() ); + printer.print_cpp2( "}; })", n.position() ); } else {