tint/utils: Remove non-const accessors on VectorRef

Nothing uses these, and the mutability of these breaks
const-correctness.

Switch functions that used to return `const utils::Vector<T, N>&`
to returning `utils::VectorRef<T>`. Removes the templated size from the
public interface.

Replace all `const utils::VectorRef<T>&` with `utils::Vector<T>`,
there's no point in using yet another level of pointer indirection.

Change-Id: Ib96e3171500606d9afffbb13f40023552a74fffc
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/113021
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
This commit is contained in:
Ben Clayton 2022-12-06 19:39:02 +00:00 committed by Dawn LUCI CQ
parent 6016d1e5cd
commit 49334b05cf
20 changed files with 50 additions and 84 deletions

View File

@ -532,7 +532,7 @@ std::vector<ResourceBinding> Inspector::GetExternalTextureResourceBindings(
ResourceBinding::ResourceType::kExternalTexture);
}
utils::Vector<sem::SamplerTexturePair, 4> Inspector::GetSamplerTextureUses(
utils::VectorRef<sem::SamplerTexturePair> Inspector::GetSamplerTextureUses(
const std::string& entry_point) {
auto* func = FindEntryPointByName(entry_point);
if (!func) {

View File

@ -126,7 +126,7 @@ class Inspector {
/// @param entry_point name of the entry point to get information about.
/// @returns vector of all of the sampler/texture sampling pairs that are used
/// by that entry point.
utils::Vector<sem::SamplerTexturePair, 4> GetSamplerTextureUses(const std::string& entry_point);
utils::VectorRef<sem::SamplerTexturePair> GetSamplerTextureUses(const std::string& entry_point);
/// @param entry_point name of the entry point to get information about.
/// @param placeholder the sampler binding point to use for texture-only

View File

@ -12,7 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "src/tint/ast/call_statement.h"
#include "src/tint/ast/disable_validation_attribute.h"
#include "src/tint/ast/id_attribute.h"
@ -33,16 +34,13 @@ using namespace tint::number_suffixes; // NOLINT
namespace tint::inspector {
namespace {
// All the tests that descend from InspectorBuilder are expected to define their
// test state via building up the AST through InspectorBuilder and then generate
// the program with ::Build.
// The returned Inspector from ::Build can then be used to test expecations.
// All the tests that descend from InspectorBuilder are expected to define their test state via
// building up the AST through InspectorBuilder and then generate the program with ::Build. The
// returned Inspector from ::Build can then be used to test expectations.
//
// All the tests that descend from InspectorRunner are expected to define their
// test state via a WGSL shader, which will be parsed to generate a Program and
// Inspector in ::Initialize.
// The returned Inspector from ::Initialize can then be used to test
// expecations.
// All the tests that descend from InspectorRunner are expected to define their test state via a
// WGSL shader, which will be parsed to generate a Program and Inspector in ::Initialize. The
// returned Inspector from ::Initialize can then be used to test expectations.
class InspectorGetEntryPointTest : public InspectorBuilder, public testing::Test {};
@ -3202,7 +3200,7 @@ fn main(@location(0) fragUV: vec2<f32>,
})";
Inspector& inspector = Initialize(shader);
auto result = inspector.GetSamplerTextureUses("foo");
inspector.GetSamplerTextureUses("foo");
ASSERT_TRUE(inspector.has_error()) << inspector.error();
}
@ -3224,7 +3222,8 @@ fn main(@location(0) fragUV: vec2<f32>,
auto result_1 = inspector.GetSamplerTextureUses("main");
ASSERT_FALSE(inspector.has_error()) << inspector.error();
EXPECT_EQ(result_0, result_1);
EXPECT_EQ((utils::Vector<tint::sem::SamplerTexturePair, 4>(result_0)),
(utils::Vector<tint::sem::SamplerTexturePair, 4>(result_1)));
}
TEST_F(InspectorGetSamplerTextureUsesTest, BothIndirect) {
@ -3641,7 +3640,7 @@ fn main(@location(0) fragUV: vec2<f32>,
})";
Inspector& inspector = Initialize(shader);
auto result = inspector.GetSamplerTextureUses("main");
inspector.GetSamplerTextureUses("main");
}
} // namespace

View File

@ -77,7 +77,7 @@ Switch* Builder::CreateSwitch(const ast::SwitchStatement* stmt) {
return ir_switch;
}
Block* Builder::CreateCase(Switch* s, const utils::VectorRef<const ast::CaseSelector*> selectors) {
Block* Builder::CreateCase(Switch* s, utils::VectorRef<const ast::CaseSelector*> selectors) {
s->cases.Push(Switch::Case{selectors, CreateBlock()});
Block* b = s->cases.Back().start_target;

View File

@ -78,7 +78,7 @@ class Builder {
/// @param s the switch to create the case into
/// @param selectors the case selectors for the case statement
/// @returns the start block for the case flow node
Block* CreateCase(Switch* s, const utils::VectorRef<const ast::CaseSelector*> selectors);
Block* CreateCase(Switch* s, utils::VectorRef<const ast::CaseSelector*> selectors);
/// Branches the given block to the given flow node.
/// @param from the block to branch from

View File

@ -33,7 +33,7 @@ class Switch : public Castable<Switch, FlowNode> {
/// A case label in the struct
struct Case {
/// The case selector for this node
const utils::VectorRef<const ast::CaseSelector*> selectors;
utils::Vector<const ast::CaseSelector*, 4> selectors;
/// The start block for the case block.
Block* start_target;
};

View File

@ -1745,7 +1745,7 @@ const sem::Type* Resolver::ConcreteType(const sem::Type* ty,
return nullptr;
},
[&](const sem::Struct* s) -> const sem::Type* {
if (auto& tys = s->ConcreteTypes(); !tys.IsEmpty()) {
if (auto tys = s->ConcreteTypes(); !tys.IsEmpty()) {
return target_ty ? target_ty : tys[0];
}
return nullptr;

View File

@ -1811,7 +1811,7 @@ bool Validator::Matrix(const sem::Matrix* ty, const Source& source) const {
return true;
}
bool Validator::PipelineStages(const utils::VectorRef<sem::Function*> entry_points) const {
bool Validator::PipelineStages(utils::VectorRef<sem::Function*> entry_points) const {
auto backtrace = [&](const sem::Function* func, const sem::Function* entry_point) {
if (func != entry_point) {
TraverseCallChain(diagnostics_, entry_point, func, [&](const sem::Function* f) {
@ -1906,7 +1906,7 @@ bool Validator::PipelineStages(const utils::VectorRef<sem::Function*> entry_poin
return true;
}
bool Validator::PushConstants(const utils::VectorRef<sem::Function*> entry_points) const {
bool Validator::PushConstants(utils::VectorRef<sem::Function*> entry_points) const {
for (auto* entry_point : entry_points) {
// State checked and modified by check_push_constant so that it remembers previously seen
// push_constant variables for an entry-point.
@ -2422,7 +2422,7 @@ bool Validator::CheckTypeAccessAddressSpace(
const sem::Type* store_ty,
ast::Access access,
ast::AddressSpace address_space,
const utils::VectorRef<const tint::ast::Attribute*> attributes,
utils::VectorRef<const tint::ast::Attribute*> attributes,
const Source& source) const {
if (!AddressSpaceLayout(store_ty, address_space, source)) {
return false;

View File

@ -135,12 +135,12 @@ class Validator {
/// Validates pipeline stages
/// @param entry_points the entry points to the module
/// @returns true on success, false otherwise.
bool PipelineStages(const utils::VectorRef<sem::Function*> entry_points) const;
bool PipelineStages(utils::VectorRef<sem::Function*> entry_points) const;
/// Validates push_constant variables
/// @param entry_points the entry points to the module
/// @returns true on success, false otherwise.
bool PushConstants(const utils::VectorRef<sem::Function*> entry_points) const;
bool PushConstants(utils::VectorRef<sem::Function*> entry_points) const;
/// Validates aliases
/// @param alias the alias to validate
@ -508,7 +508,7 @@ class Validator {
bool CheckTypeAccessAddressSpace(const sem::Type* store_ty,
ast::Access access,
ast::AddressSpace address_space,
const utils::VectorRef<const tint::ast::Attribute*> attributes,
utils::VectorRef<const tint::ast::Attribute*> attributes,
const Source& source) const;
SymbolTable& symbols_;
diag::List& diagnostics_;

View File

@ -135,9 +135,7 @@ class Function final : public Castable<Function, CallTarget> {
/// @returns the list of texture/sampler pairs that this function uses
/// (directly or indirectly).
const utils::Vector<VariablePair, 8>& TextureSamplerPairs() const {
return texture_sampler_pairs_;
}
utils::VectorRef<VariablePair> TextureSamplerPairs() const { return texture_sampler_pairs_; }
/// @returns the list of direct calls to functions / builtins made by this
/// function

View File

@ -39,7 +39,7 @@ class Module final : public Castable<Module, Node> {
~Module() override;
/// @returns the dependency-ordered global declarations for the module
const utils::Vector<const ast::Node*, 64>& DependencyOrderedDeclarations() const {
utils::VectorRef<const ast::Node*> DependencyOrderedDeclarations() const {
return dep_ordered_decls_;
}

View File

@ -163,7 +163,7 @@ class Struct final : public Castable<Struct, Type> {
/// @returns the conversion-rank ordered concrete versions of this abstract structure, or an
/// empty vector if this structure is not abstract.
/// @note only structures returned by builtins may be abstract (e.g. modf, frexp)
const utils::Vector<const Struct*, 2>& ConcreteTypes() const { return concrete_types_; }
utils::VectorRef<const Struct*> ConcreteTypes() const { return concrete_types_; }
private:
ast::Struct const* const declaration_;

View File

@ -239,7 +239,7 @@ uint32_t Type::ConversionRank(const Type* from, const Type* to) {
return kNoConversion;
},
[&](const Struct* from_str) {
auto& concrete_tys = from_str->ConcreteTypes();
auto concrete_tys = from_str->ConcreteTypes();
for (size_t i = 0; i < concrete_tys.Length(); i++) {
if (concrete_tys[i] == to) {
return static_cast<uint32_t>(i + 1);

View File

@ -228,7 +228,8 @@ struct DirectVariableAccess::State {
// will have the pointer parameters replaced with an array of u32s, used to perform the
// pointer indexing in the variant.
// Function call pointer arguments are replaced with an array of these dynamic indices.
for (auto* decl : utils::Reverse(sem.Module()->DependencyOrderedDeclarations())) {
auto decls = sem.Module()->DependencyOrderedDeclarations();
for (auto* decl : utils::Reverse(decls)) {
if (auto* fn = sem.Get<sem::Function>(decl)) {
auto* fn_info = FnInfoFor(fn);
ProcessFunction(fn, fn_info);

View File

@ -91,8 +91,7 @@ auto Transform(const Vector<IN, N>& in, TRANSFORMER&& transform)
/// @tparam N the small-array size of the returned Vector
/// @returns a new vector with each element of the source vector transformed by `transform`.
template <size_t N, typename IN, typename TRANSFORMER>
auto Transform(const VectorRef<IN>& in, TRANSFORMER&& transform)
-> Vector<decltype(transform(in[0])), N> {
auto Transform(VectorRef<IN> in, TRANSFORMER&& transform) -> Vector<decltype(transform(in[0])), N> {
const auto count = in.Length();
Vector<decltype(transform(in[0])), N> result;
result.Reserve(count);
@ -108,7 +107,7 @@ auto Transform(const VectorRef<IN>& in, TRANSFORMER&& transform)
/// @tparam N the small-array size of the returned Vector
/// @returns a new vector with each element of the source vector transformed by `transform`.
template <size_t N, typename IN, typename TRANSFORMER>
auto Transform(const VectorRef<IN>& in, TRANSFORMER&& transform)
auto Transform(VectorRef<IN> in, TRANSFORMER&& transform)
-> Vector<decltype(transform(in[0], 1u)), N> {
const auto count = in.Length();
Vector<decltype(transform(in[0], 1u)), N> result;

View File

@ -87,8 +87,8 @@ struct UniqueVector {
/// @returns an iterator to the end of the reversed vector
auto rend() const { return vector.rend(); }
/// @returns a const reference to the internal vector
operator const Vector<T, N>&() const { return vector; }
/// @returns a reference to the internal vector
operator VectorRef<T>() const { return vector; }
/// @returns the std::move()'d vector.
/// @note The UniqueVector must not be used after calling this method

View File

@ -94,11 +94,11 @@ TEST(UniqueVectorTest, AsVector) {
unique_vec.Add(1);
unique_vec.Add(2);
const utils::Vector<int, 4>& vec = unique_vec;
EXPECT_EQ(vec.Length(), 3u);
utils::VectorRef<int> ref = unique_vec;
EXPECT_EQ(ref.Length(), 3u);
EXPECT_EQ(unique_vec.IsEmpty(), false);
int i = 0;
for (auto n : vec) {
for (auto n : ref) {
EXPECT_EQ(n, i);
i++;
}

View File

@ -680,11 +680,11 @@ template <typename... Ts>
Vector(Ts...) -> Vector<VectorCommonType<Ts...>, sizeof...(Ts)>;
/// VectorRef is a weak reference to a Vector, used to pass vectors as parameters, avoiding copies
/// between the caller and the callee. VectorRef can accept a Vector of any 'N' value, decoupling
/// the caller's vector internal size from the callee's vector size. A VectorRef tracks the usage of
/// moves either side of the call. If at the call site, a Vector argument is moved to a VectorRef
/// parameter, and within the callee, the VectorRef parameter is moved to a Vector, then the Vector
/// heap allocation will be moved. For example:
/// between the caller and the callee, or as an non-static sized accessor on a vector. VectorRef can
/// accept a Vector of any 'N' value, decoupling the caller's vector internal size from the callee's
/// vector size. A VectorRef tracks the usage of moves either side of the call. If at the call site,
/// a Vector argument is moved to a VectorRef parameter, and within the callee, the VectorRef
/// parameter is moved to a Vector, then the Vector heap allocation will be moved. For example:
///
/// ```
/// void func_a() {
@ -698,6 +698,8 @@ Vector(Ts...) -> Vector<VectorCommonType<Ts...>, sizeof...(Ts)>;
/// Vector<std::string, 2> vec(std::move(vec_ref));
/// }
/// ```
///
/// Aside from this move pattern, a VectorRef provides an immutable reference to the Vector.
template <typename T>
class VectorRef {
/// The slice type used by this vector reference
@ -710,6 +712,9 @@ class VectorRef {
}
public:
/// Type of `T`.
using value_type = T;
/// Constructor - empty reference
VectorRef() : slice_(EmptySlice()) {}
@ -804,39 +809,21 @@ class VectorRef {
/// @returns true if the vector is empty.
bool IsEmpty() const { return slice_.len == 0; }
/// @returns a reference to the first element in the vector
T& Front() { return slice_.Front(); }
/// @returns a reference to the first element in the vector
const T& Front() const { return slice_.Front(); }
/// @returns a reference to the last element in the vector
T& Back() { return slice_.Back(); }
/// @returns a reference to the last element in the vector
const T& Back() const { return slice_.Back(); }
/// @returns a pointer to the first element in the vector
T* begin() { return slice_.begin(); }
/// @returns a pointer to the first element in the vector
const T* begin() const { return slice_.begin(); }
/// @returns a pointer to one past the last element in the vector
T* end() { return slice_.end(); }
/// @returns a pointer to one past the last element in the vector
const T* end() const { return slice_.end(); }
/// @returns a reverse iterator starting with the last element in the vector
auto rbegin() { return slice_.rbegin(); }
/// @returns a reverse iterator starting with the last element in the vector
auto rbegin() const { return slice_.rbegin(); }
/// @returns the end for a reverse iterator
auto rend() { return slice_.rend(); }
/// @returns the end for a reverse iterator
auto rend() const { return slice_.rend(); }
@ -907,7 +894,7 @@ inline std::ostream& operator<<(std::ostream& o, const utils::Vector<T, N>& vec)
/// @param vec the vector reference
/// @return the std::ostream so calls can be chained
template <typename T>
inline std::ostream& operator<<(std::ostream& o, const utils::VectorRef<T>& vec) {
inline std::ostream& operator<<(std::ostream& o, utils::VectorRef<T> vec) {
o << "[";
bool first = true;
for (auto& el : vec) {

View File

@ -2072,15 +2072,6 @@ TEST(TintVectorRefTest, IsEmpty) {
}
TEST(TintVectorRefTest, FrontBack) {
Vector<std::string, 3> vec{"front", "mid", "back"};
VectorRef<std::string> vec_ref(vec);
static_assert(!std::is_const_v<std::remove_reference_t<decltype(vec_ref.Front())>>);
static_assert(!std::is_const_v<std::remove_reference_t<decltype(vec_ref.Back())>>);
EXPECT_EQ(vec_ref.Front(), "front");
EXPECT_EQ(vec_ref.Back(), "back");
}
TEST(TintVectorRefTest, ConstFrontBack) {
Vector<std::string, 3> vec{"front", "mid", "back"};
const VectorRef<std::string> vec_ref(vec);
static_assert(std::is_const_v<std::remove_reference_t<decltype(vec_ref.Front())>>);
@ -2090,15 +2081,6 @@ TEST(TintVectorRefTest, ConstFrontBack) {
}
TEST(TintVectorRefTest, BeginEnd) {
Vector<std::string, 3> vec{"front", "mid", "back"};
VectorRef<std::string> vec_ref(vec);
static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec_ref.begin())>>);
static_assert(!std::is_const_v<std::remove_reference_t<decltype(*vec_ref.end())>>);
EXPECT_EQ(vec_ref.begin(), &vec[0]);
EXPECT_EQ(vec_ref.end(), &vec[0] + 3);
}
TEST(TintVectorRefTest, ConstBeginEnd) {
Vector<std::string, 3> vec{"front", "mid", "back"};
const VectorRef<std::string> vec_ref(vec);
static_assert(std::is_const_v<std::remove_reference_t<decltype(*vec_ref.begin())>>);

View File

@ -442,8 +442,8 @@ TEST_F(BuilderTest_Type, GenerateStruct_DecoratedMembers_ArraysOfMatrix) {
auto* arr_arr_mat2x3_f32 =
ty.array(ty.array(ty.mat2x3<f32>(), 1_u), 2_u); // Doubly nested array
auto* arr_arr_mat2x3_f16 =
ty.array(ty.array(ty.mat2x3<f16>(), 1_u), 2_u); // Doubly nested array
auto* rtarr_mat4x4 = ty.array(ty.mat4x4<f32>()); // Runtime array
ty.array(ty.array(ty.mat2x3<f16>(), 1_u), 2_u); // Doubly nested array
auto* rtarr_mat4x4 = ty.array(ty.mat4x4<f32>()); // Runtime array
auto* s = Structure(
"S", utils::Vector{