Skip to content
This repository was archived by the owner on Jan 29, 2026. It is now read-only.

Commit 46fe435

Browse files
authored
Bypass proxiability check in unresolved context (#255)
1 parent 777510b commit 46fe435

2 files changed

Lines changed: 56 additions & 4 deletions

File tree

proxy.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,11 +332,19 @@ struct overload_traits<R(Args...) const&& noexcept>
332332
: overload_traits_impl<qualifier_type::const_rv, true, R, Args...> {};
333333

334334
template <class O>
335-
struct overload_substitution_traits : inapplicable_traits
336-
{ template <class> using type = O; };
335+
struct overload_substitution_traits : inapplicable_traits {
336+
template <class> using type = O;
337+
template <bool IsDirect, class D, class P>
338+
static constexpr bool applicable_ptr =
339+
overload_traits<O>::template applicable_ptr<IsDirect, D, P>;
340+
};
337341
template <template <class> class O>
338342
struct overload_substitution_traits<facade_aware_overload_t<O>>
339-
: applicable_traits { template <class F> using type = O<F>; };
343+
: applicable_traits {
344+
template <class F> using type = O<F>;
345+
template <bool IsDirect, class D, class P>
346+
static constexpr bool applicable_ptr = true;
347+
};
340348
template <class O, class F>
341349
using substituted_overload_t =
342350
typename overload_substitution_traits<O>::template type<F>;
@@ -393,7 +401,7 @@ struct conv_traits_impl<C, F, Os...> : applicable_traits {
393401

394402
template <class P>
395403
static constexpr bool applicable_ptr =
396-
(overload_traits<substituted_overload_t<Os, F>>::template applicable_ptr<
404+
(overload_substitution_traits<Os>::template applicable_ptr<
397405
C::is_direct, typename C::dispatch_type, P> && ...);
398406
};
399407
template <class C, class F> struct conv_traits : inapplicable_traits {};

tests/proxy_regression_tests.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,41 @@
22
// Licensed under the MIT License.
33

44
#include <gtest/gtest.h>
5+
#include <vector>
56
#include "proxy.h"
67

8+
namespace proxy_regression_tests_details {
9+
10+
template <class It, class F>
11+
bool operator==(const It& it, const pro::proxy<F>& rhs) noexcept
12+
requires(!std::is_same_v<It, pro::proxy<F>>) {
13+
return typeid(It) == proxy_typeid(rhs) && it == proxy_cast<const It&>(rhs);
14+
}
15+
16+
template <class F>
17+
using SelfComparisonOverload = bool(const pro::proxy<F>& rhs) const noexcept;
18+
19+
template <class T>
20+
struct Iterator : pro::facade_builder
21+
::support_direct_rtti
22+
::restrict_layout<4 * sizeof(void*)>
23+
::add_direct_convention<pro::operator_dispatch<"++">, void() noexcept>
24+
::add_direct_convention<pro::operator_dispatch<"!=">, pro::facade_aware_overload_t<SelfComparisonOverload>>
25+
::add_convention<pro::implicit_conversion_dispatch, T&() const noexcept>
26+
::build {};
27+
28+
PRO_DEF_MEM_DISPATCH(MemBegin, begin);
29+
PRO_DEF_MEM_DISPATCH(MemEnd, end);
30+
template <class T>
31+
struct Range : pro::facade_builder
32+
::add_convention<MemBegin, pro::proxy<Iterator<T>>()>
33+
::template add_convention<MemEnd, pro::proxy<Iterator<T>>()>
34+
::build {};
35+
36+
} // namespace proxy_regression_tests_details
37+
38+
namespace details = proxy_regression_tests_details;
39+
740
// https://github.com/microsoft/proxy/issues/213
841
TEST(ProxyRegressionTests, TestUnexpectedCompilerWarning) {
942
struct MyTrivialFacade : pro::facade_builder
@@ -17,3 +50,14 @@ TEST(ProxyRegressionTests, TestUnexpectedCompilerWarning) {
1750
(*p)();
1851
EXPECT_EQ(side_effect, 1);
1952
}
53+
54+
// https://github.com/microsoft/proxy/issues/254
55+
TEST(ProxyRegressionTests, TestProxiableSelfDependency) {
56+
std::vector<int> original{1, 2, 123};
57+
std::vector<int> expected;
58+
pro::proxy<details::Range<int>> p = &original;
59+
for (int i : *p) {
60+
expected.push_back(i);
61+
}
62+
EXPECT_EQ(expected, original);
63+
}

0 commit comments

Comments
 (0)