Skip to content

Commit 6b48a72

Browse files
committed
Give better diagnostic for invalid comparisons, closes #817
1 parent 76c2941 commit 6b48a72

File tree

5 files changed

+67
-16
lines changed

5 files changed

+67
-16
lines changed

include/cpp2util.h

Lines changed: 59 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -862,11 +862,23 @@ class out {
862862
//
863863
//-----------------------------------------------------------------------
864864
//
865+
// For use when returning "no such thing", such as
866+
// when customizing "as" for std::variant
867+
struct nonesuch_ {
868+
auto operator==(auto const&) -> bool { return false; }
869+
};
870+
constexpr inline nonesuch_ nonesuch;
871+
865872
inline auto to_string(...) -> std::string
866873
{
867874
return "(customize me - no cpp2::to_string overload exists for this type)";
868875
}
869876

877+
inline auto to_string(nonesuch_) -> std::string
878+
{
879+
return "(invalid type)";
880+
}
881+
870882
inline auto to_string(std::same_as<std::any> auto const&) -> std::string
871883
{
872884
return "std::any";
@@ -1093,13 +1105,6 @@ inline constexpr auto is( auto const& x, auto const& value ) -> bool
10931105
// Built-in as
10941106
//
10951107

1096-
// For use when returning "no such thing", such as
1097-
// when customizing "as" for std::variant
1098-
struct nonesuch_ {
1099-
auto operator==(auto const&) -> bool { return false; }
1100-
};
1101-
constexpr inline nonesuch_ nonesuch;
1102-
11031108
// The 'as' cast functions are <To, From> so use that order here
11041109
// If it's confusing, we can switch this to <From, To>
11051110
template< typename To, typename From >
@@ -1786,34 +1791,80 @@ CPP2_FORCE_INLINE constexpr auto cmp_mixed_signedness_check() -> void
17861791
// static_assert to reject the comparison is the right way to go.
17871792
static_assert(
17881793
program_violates_type_safety_guarantee<T, U>,
1789-
"mixed signed/unsigned comparison is unsafe - prefer using .ssize() instead of .size(), consider using std::cmp_less instead, or consider explicitly casting one of the values to change signedness by using 'as' or 'cpp2::unsafe_narrow'");
1794+
"mixed signed/unsigned comparison is unsafe - prefer using .ssize() instead of .size(), consider using std::cmp_less instead, or consider explicitly casting one of the values to change signedness by using 'as' or 'cpp2::unsafe_narrow'"
1795+
);
17901796
}
17911797
}
17921798

1799+
17931800
CPP2_FORCE_INLINE constexpr auto cmp_less(auto&& t, auto&& u) -> decltype(auto)
1801+
requires requires {CPP2_FORWARD(t) < CPP2_FORWARD(u);}
17941802
{
17951803
cmp_mixed_signedness_check<CPP2_TYPEOF(t), CPP2_TYPEOF(u)>();
17961804
return CPP2_FORWARD(t) < CPP2_FORWARD(u);
17971805
}
17981806

1807+
CPP2_FORCE_INLINE constexpr auto cmp_less(auto&& t, auto&& u) -> decltype(auto)
1808+
{
1809+
static_assert(
1810+
program_violates_type_safety_guarantee<decltype(t), decltype(u)>,
1811+
"attempted to compare '<' for incompatible types"
1812+
);
1813+
return nonesuch;
1814+
}
1815+
1816+
17991817
CPP2_FORCE_INLINE constexpr auto cmp_less_eq(auto&& t, auto&& u) -> decltype(auto)
1818+
requires requires {CPP2_FORWARD(t) <= CPP2_FORWARD(u);}
18001819
{
18011820
cmp_mixed_signedness_check<CPP2_TYPEOF(t), CPP2_TYPEOF(u)>();
18021821
return CPP2_FORWARD(t) <= CPP2_FORWARD(u);
18031822
}
18041823

1824+
CPP2_FORCE_INLINE constexpr auto cmp_less_eq(auto&& t, auto&& u) -> decltype(auto)
1825+
{
1826+
static_assert(
1827+
program_violates_type_safety_guarantee<decltype(t), decltype(u)>,
1828+
"attempted to compare '<=' for incompatible types"
1829+
);
1830+
return nonesuch;
1831+
}
1832+
1833+
18051834
CPP2_FORCE_INLINE constexpr auto cmp_greater(auto&& t, auto&& u) -> decltype(auto)
1835+
requires requires {CPP2_FORWARD(t) > CPP2_FORWARD(u);}
18061836
{
18071837
cmp_mixed_signedness_check<CPP2_TYPEOF(t), CPP2_TYPEOF(u)>();
18081838
return CPP2_FORWARD(t) > CPP2_FORWARD(u);
18091839
}
18101840

1841+
CPP2_FORCE_INLINE constexpr auto cmp_greater(auto&& t, auto&& u) -> decltype(auto)
1842+
{
1843+
static_assert(
1844+
program_violates_type_safety_guarantee<decltype(t), decltype(u)>,
1845+
"attempted to compare '>' for incompatible types"
1846+
);
1847+
return nonesuch;
1848+
}
1849+
1850+
18111851
CPP2_FORCE_INLINE constexpr auto cmp_greater_eq(auto&& t, auto&& u) -> decltype(auto)
1852+
requires requires {CPP2_FORWARD(t) >= CPP2_FORWARD(u);}
18121853
{
18131854
cmp_mixed_signedness_check<CPP2_TYPEOF(t), CPP2_TYPEOF(u)>();
18141855
return CPP2_FORWARD(t) >= CPP2_FORWARD(u);
18151856
}
18161857

1858+
CPP2_FORCE_INLINE constexpr auto cmp_greater_eq(auto&& t, auto&& u) -> decltype(auto)
1859+
{
1860+
static_assert(
1861+
program_violates_type_safety_guarantee<decltype(t), decltype(u)>,
1862+
"attempted to compare '>=' for incompatible types"
1863+
);
1864+
return nonesuch;
1865+
}
1866+
1867+
18171868

18181869
//-----------------------------------------------------------------------
18191870
//

regression-tests/test-results/gcc-10/pure2-bugfix-for-requires-clause-in-forward-declaration.cpp.output

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@ pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:46: error: expect
1111
In file included from pure2-bugfix-for-requires-clause-in-forward-declaration.cpp:7:
1212
../../../include/cpp2util.h:10005:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10.
1313
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:4:1: note: in expansion of macro ‘CPP2_REQUIRES_’
14-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:3: error: no declaration matches ‘element::element(auto:82&&) requires is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(element::__ct ::n)>::type>::type, std::__cxx11::string>’
14+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:3: error: no declaration matches ‘element::element(auto:90&&) requires is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(element::__ct ::n)>::type>::type, std::__cxx11::string>’
1515
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:5:11: note: candidates are: ‘element::element(const element&)’
16-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp:16:20: note: ‘template<class auto:80> element::element(auto:80&&)’
16+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp:16:20: note: ‘template<class auto:88> element::element(auto:88&&)’
1717
16 | public: explicit element(auto&& n)
1818
| ^~~~~~~
1919
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp:14:7: note: ‘class element’ defined here
2020
14 | class element {
2121
| ^~~~~~~
2222
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:3: error: expected unqualified-id before ‘{’ token
23-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:8: error: no declaration matches ‘element& element::operator=(auto:83&&) requires is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(element::operator=::n)>::type>::type, std::__cxx11::string>’
23+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:8: error: no declaration matches ‘element& element::operator=(auto:91&&) requires is_same_v<typename std::remove_cv<typename std::remove_reference<decltype(element::operator=::n)>::type>::type, std::__cxx11::string>’
2424
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:6:16: note: candidates are: ‘void element::operator=(const element&)’
25-
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:16: note: ‘template<class auto:81> element& element::operator=(auto:81&&)’
25+
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:16: note: ‘template<class auto:89> element& element::operator=(auto:89&&)’
2626
pure2-bugfix-for-requires-clause-in-forward-declaration.cpp:14:7: note: ‘class element’ defined here
2727
14 | class element {
2828
| ^~~~~~~

regression-tests/test-results/gcc-10/pure2-print.cpp.output

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ pure2-print.cpp2:66:1: note: in expansion of macro ‘CPP2_REQUIRES_’
99
pure2-print.cpp2:94:1: note: in expansion of macro ‘CPP2_REQUIRES_’
1010
pure2-print.cpp2:6:29: error: ‘constexpr const T outer::object_alias’ is not a static data member of ‘class outer’
1111
pure2-print.cpp2:6:36: error: template definition of non-template ‘constexpr const T outer::object_alias’
12-
pure2-print.cpp2:65:14: error: no declaration matches ‘void outer::mytype::variadic(const auto:89& ...) requires (is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(outer::mytype::variadic::x)>::type>::type, int> && ...)’
13-
pure2-print.cpp2:65:29: note: candidate is: ‘template<class ... auto:80> static void outer::mytype::variadic(const auto:80& ...)’
12+
pure2-print.cpp2:65:14: error: no declaration matches ‘void outer::mytype::variadic(const auto:97& ...) requires (is_convertible_v<typename std::remove_cv<typename std::remove_reference<decltype(outer::mytype::variadic::x)>::type>::type, int> && ...)’
13+
pure2-print.cpp2:65:29: note: candidate is: ‘template<class ... auto:88> static void outer::mytype::variadic(const auto:88& ...)’
1414
pure2-print.cpp2:8:19: note: ‘class outer::mytype’ defined here
1515
pure2-print.cpp2:93:37: error: no declaration matches ‘void outer::print(std::ostream&, const Args& ...) requires cpp2::cmp_greater_eq(sizeof (Args)..., 0)’
1616
pure2-print.cpp2:93:37: note: no functions named ‘void outer::print(std::ostream&, const Args& ...) requires cpp2::cmp_greater_eq(sizeof (Args)..., 0)’

regression-tests/test-results/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
cppfront compiler v0.3.0 Build 8B09:1419
2+
cppfront compiler v0.3.0 Build 8B10:1325
33
Copyright(c) Herb Sutter All rights reserved
44

55
SPDX-License-Identifier: CC-BY-NC-ND-4.0

source/build.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"8B09:1419"
1+
"8B10:1325"

0 commit comments

Comments
 (0)