Skip to content

Commit 855c47d

Browse files
committed
fix(cpp1): contract check invalid alternative
1 parent 4376132 commit 855c47d

13 files changed

+66
-24
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
f: (x) = {
2+
[[assert: inspect x -> i32 {
3+
is 1 = :() -> bool = 2;("");
4+
is _ = 1;
5+
} == 1]]
6+
}
7+
main: () = f(1);

regression-tests/test-results/mixed-inspect-templates.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ struct my_type {};
3333
#line 8 "mixed-inspect-templates.cpp2"
3434
[[nodiscard]] auto fun(auto const& v) -> std::string{
3535
return [&] () -> std::string { auto&& __expr = v;
36-
if (cpp2::is<std::vector>(__expr)) { if constexpr( requires{"std::vector";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("std::vector")),std::string> ) return "std::vector"; else return std::string{}; else return std::string{}; }
37-
else if (cpp2::is<std::array>(__expr)) { if constexpr( requires{"std::array";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("std::array")),std::string> ) return "std::array"; else return std::string{}; else return std::string{}; }
38-
else if (cpp2::is<std::variant>(__expr)) { if constexpr( requires{"std::variant";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("std::variant")),std::string> ) return "std::variant"; else return std::string{}; else return std::string{}; }
39-
else if (cpp2::is<my_type>(__expr)) { if constexpr( requires{"my_type";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("my_type")),std::string> ) return "my_type"; else return std::string{}; else return std::string{}; }
36+
if (cpp2::is<std::vector>(__expr)) { if constexpr( requires{"std::vector";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("std::vector")),std::string> ) return "std::vector"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
37+
else if (cpp2::is<std::array>(__expr)) { if constexpr( requires{"std::array";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("std::array")),std::string> ) return "std::array"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
38+
else if (cpp2::is<std::variant>(__expr)) { if constexpr( requires{"std::variant";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("std::variant")),std::string> ) return "std::variant"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
39+
else if (cpp2::is<my_type>(__expr)) { if constexpr( requires{"my_type";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("my_type")),std::string> ) return "my_type"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
4040
else return "unknown"; }
4141
();
4242
}

regression-tests/test-results/mixed-inspect-values-2.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ constexpr auto empty = [](auto&& x){
3939
auto i {15};
4040

4141
std::cout << [&] () -> std::string { auto&& __expr = i;
42-
if (cpp2::is(__expr, (less_than(10)))) { if constexpr( requires{"i less than 10";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("i less than 10")),std::string> ) return "i less than 10"; else return std::string{}; else return std::string{}; }
43-
else if (cpp2::is(__expr, in(11, 20))) { if constexpr( requires{"i is between 11 and 20";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("i is between 11 and 20")),std::string> ) return "i is between 11 and 20"; else return std::string{}; else return std::string{}; }
42+
if (cpp2::is(__expr, (less_than(10)))) { if constexpr( requires{"i less than 10";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("i less than 10")),std::string> ) return "i less than 10"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
43+
else if (cpp2::is(__expr, in(11, 20))) { if constexpr( requires{"i is between 11 and 20";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("i is between 11 and 20")),std::string> ) return "i is between 11 and 20"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
4444
else return "i is out of our interest"; }
4545
() << std::endl;
4646

regression-tests/test-results/mixed-inspect-values.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ auto test(auto const& x) -> void;
5656
auto test(auto const& x) -> void{
5757
auto forty_two {42};
5858
std::cout << [&] () -> std::string { auto&& __expr = x;
59-
if (cpp2::is(__expr, 0)) { if constexpr( requires{"zero";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("zero")),std::string> ) return "zero"; else return std::string{}; else return std::string{}; }
60-
else if (cpp2::is(__expr, (in(1, 2)))) { if constexpr( requires{"1 or 2";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("1 or 2")),std::string> ) return "1 or 2"; else return std::string{}; else return std::string{}; }
61-
else if (cpp2::is(__expr, in_2_3)) { if constexpr( requires{"3";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("3")),std::string> ) return "3"; else return std::string{}; else return std::string{}; }
62-
else if (cpp2::is(__expr, std::move(forty_two))) { if constexpr( requires{"the answer";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("the answer")),std::string> ) return "the answer"; else return std::string{}; else return std::string{}; }
63-
else if (cpp2::is<int>(__expr)) { if constexpr( requires{"integer " + cpp2::to_string(x);} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("integer " + cpp2::to_string(x))),std::string> ) return "integer " + cpp2::to_string(x); else return std::string{}; else return std::string{}; }
64-
else if (cpp2::is<std::string>(__expr)) { if constexpr( requires{cpp2::as<std::string>(x);} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((cpp2::as<std::string>(x))),std::string> ) return cpp2::as<std::string>(x); else return std::string{}; else return std::string{}; }
59+
if (cpp2::is(__expr, 0)) { if constexpr( requires{"zero";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("zero")),std::string> ) return "zero"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
60+
else if (cpp2::is(__expr, (in(1, 2)))) { if constexpr( requires{"1 or 2";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("1 or 2")),std::string> ) return "1 or 2"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
61+
else if (cpp2::is(__expr, in_2_3)) { if constexpr( requires{"3";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("3")),std::string> ) return "3"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
62+
else if (cpp2::is(__expr, std::move(forty_two))) { if constexpr( requires{"the answer";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("the answer")),std::string> ) return "the answer"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
63+
else if (cpp2::is<int>(__expr)) { if constexpr( requires{"integer " + cpp2::to_string(x);} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("integer " + cpp2::to_string(x))),std::string> ) return "integer " + cpp2::to_string(x); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
64+
else if (cpp2::is<std::string>(__expr)) { if constexpr( requires{cpp2::as<std::string>(x);} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((cpp2::as<std::string>(x))),std::string> ) return cpp2::as<std::string>(x); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
6565
else return "(no match)"; }
6666
() << "\n";
6767
}

regression-tests/test-results/mixed-inspect-with-typeof-of-template-arg-list.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ auto calc() {
2929
#line 7 "mixed-inspect-with-typeof-of-template-arg-list.cpp2"
3030
[[nodiscard]] auto fun(auto const& v) -> int{
3131
return [&] () -> int { auto&& __expr = v;
32-
if (cpp2::is<int>(__expr)) { if constexpr( requires{calc<1,2>();} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((calc<1,2>())),int> ) return calc<1,2>(); else return int{}; else return int{}; }
32+
if (cpp2::is<int>(__expr)) { if constexpr( requires{calc<1,2>();} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((calc<1,2>())),int> ) return calc<1,2>(); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
3333
else return 0; }
3434
();
3535
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
#define CPP2_USE_MODULES Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
10+
11+
//=== Cpp2 type definitions and function declarations ===========================
12+
13+
#line 1 "pure2-bugfix-for-runtime-invalid-alternative.cpp2"
14+
auto f(auto const& x) -> void;
15+
16+
17+
#line 7 "pure2-bugfix-for-runtime-invalid-alternative.cpp2"
18+
auto main() -> int;
19+
20+
21+
//=== Cpp2 function definitions =================================================
22+
23+
#line 1 "pure2-bugfix-for-runtime-invalid-alternative.cpp2"
24+
auto f(auto const& x) -> void{
25+
cpp2::Default.expects([&] () -> cpp2::i32 { auto&& __expr = x;
26+
if (cpp2::is(__expr, 1)) { if constexpr( requires{[]() -> bool { return 2; }("");} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(([]() -> bool { return 2; }(""))),cpp2::i32> ) return []() -> bool { return 2; }(""); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
27+
else return 1; }
28+
()==1, "");
29+
}
30+
auto main() -> int { f(1); }
31+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-bugfix-for-runtime-invalid-alternative.cpp2... ok (all Cpp2, passes safety checks)
2+

regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ auto test_generic(auto const& x, auto const& msg) -> void{
4545
<< std::setw(30) << msg
4646
<< " value is "
4747
<< [&] () -> std::string { auto&& __expr = x;
48-
if (cpp2::is<int>(__expr)) { if constexpr( requires{"integer " + std::to_string(cpp2::as<int>(x));} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("integer " + std::to_string(cpp2::as<int>(x)))),std::string> ) return "integer " + std::to_string(cpp2::as<int>(x)); else return std::string{}; else return std::string{}; }
49-
else if (cpp2::is<std::string>(__expr)) { if constexpr( requires{'"' + cpp2::as<std::string>(x) + '"';} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(('"' + cpp2::as<std::string>(x) + '"')),std::string> ) return '"' + cpp2::as<std::string>(x) + '"'; else return std::string{}; else return std::string{}; }
48+
if (cpp2::is<int>(__expr)) { if constexpr( requires{"integer " + std::to_string(cpp2::as<int>(x));} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(("integer " + std::to_string(cpp2::as<int>(x)))),std::string> ) return "integer " + std::to_string(cpp2::as<int>(x)); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
49+
else if (cpp2::is<std::string>(__expr)) { if constexpr( requires{'"' + cpp2::as<std::string>(x) + '"';} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF(('"' + cpp2::as<std::string>(x) + '"')),std::string> ) return '"' + cpp2::as<std::string>(x) + '"'; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
5050
else return "not an int or string"; }
5151
()
5252
<< "\n";

regression-tests/test-results/pure2-inspect-expression-with-as-in-generic-function.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ auto print_an_int(auto const& x) -> void{
3232
<< std::setw(30) << cpp2::to_string(x)
3333
<< " value is "
3434
<< [&] () -> std::string { auto&& __expr = x;
35-
if (cpp2::is<int>(__expr)) { if constexpr( requires{std::to_string(cpp2::as<int>(x));} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((std::to_string(cpp2::as<int>(x)))),std::string> ) return std::to_string(cpp2::as<int>(x)); else return std::string{}; else return std::string{}; }
35+
if (cpp2::is<int>(__expr)) { if constexpr( requires{std::to_string(cpp2::as<int>(x));} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((std::to_string(cpp2::as<int>(x)))),std::string> ) return std::to_string(cpp2::as<int>(x)); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
3636
else return "not an int"; }
3737
()
3838
<< "\n";

regression-tests/test-results/pure2-inspect-fallback-with-variant-any-optional.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ auto test_generic(auto const& x, auto const& msg) -> void{
3939
std::cout
4040
<< "\n" << msg << "\n ..."
4141
<< [&] () -> std::string { auto&& __expr = x;
42-
if (cpp2::is<std::string>(__expr)) { if constexpr( requires{" matches std::string";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((" matches std::string")),std::string> ) return " matches std::string"; else return std::string{}; else return std::string{}; }
43-
else if (cpp2::is<std::variant<int,std::string>>(__expr)) { if constexpr( requires{" matches std::variant<int, std::string>";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((" matches std::variant<int, std::string>")),std::string> ) return " matches std::variant<int, std::string>"; else return std::string{}; else return std::string{}; }
44-
else if (cpp2::is<std::any>(__expr)) { if constexpr( requires{" matches std::any";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((" matches std::any")),std::string> ) return " matches std::any"; else return std::string{}; else return std::string{}; }
45-
else if (cpp2::is<std::optional<std::string>>(__expr)) { if constexpr( requires{" matches std::optional<std::string>";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((" matches std::optional<std::string>")),std::string> ) return " matches std::optional<std::string>"; else return std::string{}; else return std::string{}; }
42+
if (cpp2::is<std::string>(__expr)) { if constexpr( requires{" matches std::string";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((" matches std::string")),std::string> ) return " matches std::string"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
43+
else if (cpp2::is<std::variant<int,std::string>>(__expr)) { if constexpr( requires{" matches std::variant<int, std::string>";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((" matches std::variant<int, std::string>")),std::string> ) return " matches std::variant<int, std::string>"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
44+
else if (cpp2::is<std::any>(__expr)) { if constexpr( requires{" matches std::any";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((" matches std::any")),std::string> ) return " matches std::any"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
45+
else if (cpp2::is<std::optional<std::string>>(__expr)) { if constexpr( requires{" matches std::optional<std::string>";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((" matches std::optional<std::string>")),std::string> ) return " matches std::optional<std::string>"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
4646
else return " no match"; }
4747
()
4848
<< "\n";

regression-tests/test-results/pure2-inspect-generic-void-empty-with-variant-any-optional.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ auto test_generic(auto const& x, auto const& msg) -> void{
4343
std::cout
4444
<< "\n" << msg << "\n ..."
4545
<< [&] () -> std::string { auto&& __expr = x;
46-
if (cpp2::is<void>(__expr)) { if constexpr( requires{" VOYDE AND EMPTIE";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((" VOYDE AND EMPTIE")),std::string> ) return " VOYDE AND EMPTIE"; else return std::string{}; else return std::string{}; }
46+
if (cpp2::is<void>(__expr)) { if constexpr( requires{" VOYDE AND EMPTIE";} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((" VOYDE AND EMPTIE")),std::string> ) return " VOYDE AND EMPTIE"; cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
4747
else return " no match"; }
4848
()
4949
<< "\n";

regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ auto test_generic(auto const& x, auto const& msg) -> void{
4545
<< std::setw(30) << msg
4646
<< " value is "
4747
<< [&] () -> std::string { auto&& __expr = x;
48-
if (cpp2::is<int>(__expr)) { if constexpr( requires{std::to_string(cpp2::as<int>(x));} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((std::to_string(cpp2::as<int>(x)))),std::string> ) return std::to_string(cpp2::as<int>(x)); else return std::string{}; else return std::string{}; }
48+
if (cpp2::is<int>(__expr)) { if constexpr( requires{std::to_string(cpp2::as<int>(x));} ) if constexpr( std::is_convertible_v<CPP2_TYPEOF((std::to_string(cpp2::as<int>(x)))),std::string> ) return std::to_string(cpp2::as<int>(x)); cpp2::Type.expects(false, "Statement of chosen alternative is invalid."); }
4949
else return "not an int"; }
5050
()
5151
<< "\n";

source/cppfront.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1991,8 +1991,10 @@ class cppfront
19911991
)
19921992
{
19931993
assert(alt->statement->is_expression());
1994-
printer.print_cpp2("; else return " + result_type + "{}", alt->position());
1995-
printer.print_cpp2("; else return " + result_type + "{}", alt->position());
1994+
printer.print_cpp2(
1995+
"; cpp2::Type.expects(false, \"Statement of chosen alternative is invalid.\")",
1996+
alt->position()
1997+
);
19961998
}
19971999

19982000
printer.print_cpp2(return_suffix, alt->position());

0 commit comments

Comments
 (0)