LibGC: Add static_assert for non-GC types in root containers

This commit is contained in:
Luke Wilde 2026-05-06 21:38:08 +01:00 committed by Shannon Booth
parent 3c64e1dbbc
commit da9abd9a4c
3 changed files with 34 additions and 2 deletions

View file

@ -48,6 +48,10 @@ public:
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>& roots) const override
{
static constexpr bool KeyIsGCType = IsBaseOf<NanBoxedValue, K> || IsConvertible<K, Cell const*>;
static constexpr bool ValueIsGCType = IsBaseOf<NanBoxedValue, V> || IsConvertible<V, Cell const*>;
static_assert(KeyIsGCType || ValueIsGCType,
"RootHashMap requires at least one of key or value types to be convertible to Cell const* or derive from NanBoxedValue");
for (auto& [key, value] : *this) {
if constexpr (IsBaseOf<NanBoxedValue, K>) {
if (key.is_cell())

View file

@ -85,12 +85,14 @@ public:
virtual void gather_roots(HashMap<Cell*, GC::HeapRoot>& roots) const override
{
static_assert(IsBaseOf<NanBoxedValue, T> || IsConvertible<T, Cell const*>,
"RootVector element type must be convertible to Cell const* or derive from NanBoxedValue");
for (auto& value : *this) {
if constexpr (IsBaseOf<NanBoxedValue, T>) {
if (value.is_cell())
roots.set(&const_cast<T&>(value).as_cell(), HeapRoot { .type = HeapRoot::Type::RootVector });
} else {
roots.set(value, HeapRoot { .type = HeapRoot::Type::RootVector });
} else if constexpr (IsConvertible<T, Cell const*>) {
roots.set(const_cast<Cell*>(static_cast<Cell const*>(value)), HeapRoot { .type = HeapRoot::Type::RootVector });
}
}
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2026, Luke Wilde <luke@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
// RUN: %clang++ -Xclang -verify %plugin_opts% -c %s -o %t 2>&1
#include <LibGC/RootHashMap.h>
#include <LibGC/RootVector.h>
// RootVector with a non-GC element type should fail.
void test_root_vector_non_gc_type(GC::Heap& heap)
{
// expected-error@*{{RootVector element type must be convertible to Cell const* or derive from NanBoxedValue}}
// expected-note@+1 {{in instantiation of member function}}
GC::RootVector<int> bad_vector(heap);
}
// RootHashMap where neither key nor value is a GC type should fail.
void test_root_hash_map_non_gc_types(GC::Heap& heap)
{
// expected-error@*{{RootHashMap requires at least one of key or value types to be convertible to Cell const* or derive from NanBoxedValue}}
// expected-note@+1 {{in instantiation of member function}}
GC::RootHashMap<int, int> bad_map(heap);
}