AK+Everywhere: Make Variant::visit() respect the Variant's constness

...and fix all the instances of visit() taking non-const arguments.
This commit is contained in:
Ali Mohammad Pur 2022-01-13 17:31:00 +03:30 committed by Ali Mohammad Pur
parent d55c130df5
commit 9de33629da
Notes: sideshowbarker 2024-07-17 20:55:23 +09:00
7 changed files with 44 additions and 31 deletions

View file

@ -80,16 +80,16 @@ struct Variant<IndexType, InitialIndex> {
template<typename IndexType, typename... Ts> template<typename IndexType, typename... Ts>
struct VisitImpl { struct VisitImpl {
template<typename Visitor, IndexType CurrentIndex = 0> template<typename Self, typename Visitor, IndexType CurrentIndex = 0>
ALWAYS_INLINE static constexpr decltype(auto) visit(IndexType id, const void* data, Visitor&& visitor) requires(CurrentIndex < sizeof...(Ts)) ALWAYS_INLINE static constexpr decltype(auto) visit(Self& self, IndexType id, const void* data, Visitor&& visitor) requires(CurrentIndex < sizeof...(Ts))
{ {
using T = typename TypeList<Ts...>::template Type<CurrentIndex>; using T = typename TypeList<Ts...>::template Type<CurrentIndex>;
if (id == CurrentIndex) if (id == CurrentIndex)
return visitor(*bit_cast<T*>(data)); return visitor(*bit_cast<CopyConst<Self, T>*>(data));
if constexpr ((CurrentIndex + 1) < sizeof...(Ts)) if constexpr ((CurrentIndex + 1) < sizeof...(Ts))
return visit<Visitor, CurrentIndex + 1>(id, data, forward<Visitor>(visitor)); return visit<Self, Visitor, CurrentIndex + 1>(self, id, data, forward<Visitor>(visitor));
else else
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
@ -367,14 +367,14 @@ public:
ALWAYS_INLINE decltype(auto) visit(Fs&&... functions) ALWAYS_INLINE decltype(auto) visit(Fs&&... functions)
{ {
Visitor<Fs...> visitor { forward<Fs>(functions)... }; Visitor<Fs...> visitor { forward<Fs>(functions)... };
return VisitHelper::visit(m_index, m_data, move(visitor)); return VisitHelper::visit(*this, m_index, m_data, move(visitor));
} }
template<typename... Fs> template<typename... Fs>
ALWAYS_INLINE decltype(auto) visit(Fs&&... functions) const ALWAYS_INLINE decltype(auto) visit(Fs&&... functions) const
{ {
Visitor<Fs...> visitor { forward<Fs>(functions)... }; Visitor<Fs...> visitor { forward<Fs>(functions)... };
return VisitHelper::visit(m_index, m_data, move(visitor)); return VisitHelper::visit(*this, m_index, m_data, move(visitor));
} }
template<typename... NewTs> template<typename... NewTs>

View file

@ -31,9 +31,22 @@ TEST_CASE(visit)
bool correct = false; bool correct = false;
Variant<int, String, float> the_value { 42.0f }; Variant<int, String, float> the_value { 42.0f };
the_value.visit( the_value.visit(
[&](const int&) { correct = false; }, [&](int const&) { correct = false; },
[&](const String&) { correct = false; }, [&](String const&) { correct = false; },
[&](const float&) { correct = true; }); [&](float const&) { correct = true; });
EXPECT(correct);
}
TEST_CASE(visit_const)
{
bool correct = false;
Variant<int, String> const the_value { "42"sv };
the_value.visit(
[&](String const&) { correct = true; },
[&](auto&) {},
[&](auto const&) {});
EXPECT(correct); EXPECT(correct);
} }
@ -139,9 +152,9 @@ TEST_CASE(return_values)
MyVariant the_value { 42.0f }; MyVariant the_value { 42.0f };
float value = the_value.visit( float value = the_value.visit(
[&](const int&) { return 1.0f; }, [&](int const&) { return 1.0f; },
[&](const String&) { return 2.0f; }, [&](String const&) { return 2.0f; },
[&](const float& f) { return f; }); [&](float const& f) { return f; });
EXPECT_EQ(value, 42.0f); EXPECT_EQ(value, 42.0f);
} }
{ {
@ -157,9 +170,9 @@ TEST_CASE(return_values)
const MyVariant the_value { "str" }; const MyVariant the_value { "str" };
String value = the_value.visit( String value = the_value.visit(
[&](const int&) { return String { "wrong" }; }, [&](int const&) { return String { "wrong" }; },
[&](const String& s) { return s; }, [&](String const& s) { return s; },
[&](const float&) { return String { "wrong" }; }); [&](float const&) { return String { "wrong" }; });
EXPECT_EQ(value, "str"); EXPECT_EQ(value, "str");
} }
} }
@ -170,9 +183,9 @@ TEST_CASE(return_values_by_reference)
Variant<int, String, float> the_value { 42.0f }; Variant<int, String, float> the_value { 42.0f };
auto& value = the_value.visit( auto& value = the_value.visit(
[&](const int&) -> RefPtr<Object>& { return ref; }, [&](int const&) -> RefPtr<Object>& { return ref; },
[&](const String&) -> RefPtr<Object>& { return ref; }, [&](String const&) -> RefPtr<Object>& { return ref; },
[&](const float&) -> RefPtr<Object>& { return ref; }); [&](float const&) -> RefPtr<Object>& { return ref; });
EXPECT_EQ(ref, value); EXPECT_EQ(ref, value);
EXPECT_EQ(ref->ref_count(), 1u); EXPECT_EQ(ref->ref_count(), 1u);

View file

@ -2507,7 +2507,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter, GlobalObject&
// AssignmentExpression : LeftHandSideExpression = AssignmentExpression // AssignmentExpression : LeftHandSideExpression = AssignmentExpression
return m_lhs.visit( return m_lhs.visit(
// 1. If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, then // 1. If LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral, then
[&](NonnullRefPtr<Expression>& lhs) -> ThrowCompletionOr<Value> { [&](NonnullRefPtr<Expression> const& lhs) -> ThrowCompletionOr<Value> {
// a. Let lref be the result of evaluating LeftHandSideExpression. // a. Let lref be the result of evaluating LeftHandSideExpression.
// b. ReturnIfAbrupt(lref). // b. ReturnIfAbrupt(lref).
auto reference = TRY(lhs->to_reference(interpreter, global_object)); auto reference = TRY(lhs->to_reference(interpreter, global_object));
@ -2534,7 +2534,7 @@ Completion AssignmentExpression::execute(Interpreter& interpreter, GlobalObject&
return rhs_result; return rhs_result;
}, },
// 2. Let assignmentPattern be the AssignmentPattern that is covered by LeftHandSideExpression. // 2. Let assignmentPattern be the AssignmentPattern that is covered by LeftHandSideExpression.
[&](NonnullRefPtr<BindingPattern>& pattern) -> ThrowCompletionOr<Value> { [&](NonnullRefPtr<BindingPattern> const& pattern) -> ThrowCompletionOr<Value> {
// 3. Let rref be the result of evaluating AssignmentExpression. // 3. Let rref be the result of evaluating AssignmentExpression.
// 4. Let rval be ? GetValue(rref). // 4. Let rval be ? GetValue(rref).
auto rhs_result = TRY(m_rhs->execute(interpreter, global_object)).release_value(); auto rhs_result = TRY(m_rhs->execute(interpreter, global_object)).release_value();

View file

@ -201,7 +201,7 @@ public:
views.empend(view); views.empend(view);
return views; return views;
}, },
[](Utf8View& view) { [](Utf8View const& view) {
Vector<RegexStringView> views; Vector<RegexStringView> views;
auto it = view.begin(); auto it = view.begin();
auto previous_newline_position_it = it; auto previous_newline_position_it = it;

View file

@ -123,10 +123,10 @@ static float resolve_calc_value(CalculatedStyleValue::CalcValue const& calc_valu
{ {
return calc_value.visit( return calc_value.visit(
[](float value) { return value; }, [](float value) { return value; },
[&](Length length) { [&](Length const& length) {
return length.resolved_or_zero(layout_node, reference_for_percent).to_px(layout_node); return length.resolved_or_zero(layout_node, reference_for_percent).to_px(layout_node);
}, },
[&](NonnullOwnPtr<CalculatedStyleValue::CalcSum>& calc_sum) { [&](NonnullOwnPtr<CalculatedStyleValue::CalcSum> const& calc_sum) {
return resolve_calc_sum(calc_sum, layout_node, reference_for_percent); return resolve_calc_sum(calc_sum, layout_node, reference_for_percent);
}, },
[](auto&) { [](auto&) {
@ -173,7 +173,7 @@ static float resolve_calc_number_value(CalculatedStyleValue::CalcNumberValue con
{ {
return number_value.visit( return number_value.visit(
[](float number) { return number; }, [](float number) { return number; },
[](NonnullOwnPtr<CalculatedStyleValue::CalcNumberSum>& calc_number_sum) { [](NonnullOwnPtr<CalculatedStyleValue::CalcNumberSum> const& calc_number_sum) {
return resolve_calc_number_sum(calc_number_sum); return resolve_calc_number_sum(calc_number_sum);
}); });
} }

View file

@ -23,16 +23,16 @@ NonnullRefPtr<MediaQuery> MediaQuery::create_not_all()
String MediaFeatureValue::to_string() const String MediaFeatureValue::to_string() const
{ {
return m_value.visit( return m_value.visit(
[](String& ident) { return serialize_an_identifier(ident); }, [](String const& ident) { return serialize_an_identifier(ident); },
[](Length& length) { return length.to_string(); }, [](Length const& length) { return length.to_string(); },
[](double number) { return String::number(number); }); [](double number) { return String::number(number); });
} }
bool MediaFeatureValue::is_same_type(MediaFeatureValue const& other) const bool MediaFeatureValue::is_same_type(MediaFeatureValue const& other) const
{ {
return m_value.visit( return m_value.visit(
[&](String&) { return other.is_ident(); }, [&](String const&) { return other.is_ident(); },
[&](Length&) { return other.is_length(); }, [&](Length const&) { return other.is_length(); },
[&](double) { return other.is_number(); }); [&](double) { return other.is_number(); });
} }

View file

@ -35,13 +35,13 @@ MatchResult Supports::Condition::evaluate() const
MatchResult Supports::InParens::evaluate() const MatchResult Supports::InParens::evaluate() const
{ {
return value.visit( return value.visit(
[&](NonnullOwnPtr<Condition>& condition) { [&](NonnullOwnPtr<Condition> const& condition) {
return condition->evaluate(); return condition->evaluate();
}, },
[&](Feature& feature) { [&](Feature const& feature) {
return feature.evaluate(); return feature.evaluate();
}, },
[&](GeneralEnclosed& general_enclosed) { [&](GeneralEnclosed const& general_enclosed) {
return general_enclosed.evaluate(); return general_enclosed.evaluate();
}); });
} }