[tint] Migrate to 'fluent types'

Replace the ProgramBuilder and type::Manager over to using a common set
of templated types for type construction.

Allows for arbitrarily-deep templated type declarations instead of the
one-level declarations that were offered previously.

Change-Id: I4744417cdbbb531c6b9958d92f45d3dd5bebddac
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/137061
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index 52a73b3..4f4788f 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -76,10 +76,11 @@
 #include "src/tint/ast/while_statement.h"
 #include "src/tint/ast/workgroup_attribute.h"
 #include "src/tint/builtin/extension.h"
+#include "src/tint/builtin/fluent_types.h"
 #include "src/tint/builtin/interpolation_sampling.h"
 #include "src/tint/builtin/interpolation_type.h"
+#include "src/tint/builtin/number.h"
 #include "src/tint/constant/manager.h"
-#include "src/tint/number.h"
 #include "src/tint/program.h"
 #include "src/tint/program_id.h"
 #include "src/tint/sem/array_count.h"
@@ -117,13 +118,10 @@
 
 namespace tint {
 
-// A sentinel type used by some template arguments to signal that the a type should be inferred.
-struct Infer {};
-
 /// Evaluates to true if T is a Infer, AInt or AFloat.
 template <typename T>
 static constexpr const bool IsInferOrAbstract =
-    std::is_same_v<std::decay_t<T>, Infer> || IsAbstract<std::decay_t<T>>;
+    std::is_same_v<std::decay_t<T>, builtin::fluent_types::Infer> || IsAbstract<std::decay_t<T>>;
 
 // Forward declare metafunction that evaluates to true iff T can be wrapped in a statement.
 template <typename T, typename = void>
@@ -1007,17 +1005,6 @@
             return array(builder->source_, subtype, std::move(attrs));
         }
 
-        /// @param subtype the array element type
-        /// @param n the array size. nullptr represents a runtime-array
-        /// @param attrs the optional attributes for the array
-        /// @return an array of size `n` of type `T`
-        template <typename COUNT, typename = DisableIfVectorLike<COUNT>>
-        ast::Type array(ast::Type subtype,
-                        COUNT&& n,
-                        utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
-            return array(builder->source_, subtype, std::forward<COUNT>(n), std::move(attrs));
-        }
-
         /// @param source the Source of the node
         /// @param subtype the array element type
         /// @param attrs the optional attributes for the array
@@ -1033,6 +1020,17 @@
                                                           std::move(attrs)))};
         }
 
+        /// @param subtype the array element type
+        /// @param n the array size. nullptr represents a runtime-array
+        /// @param attrs the optional attributes for the array
+        /// @return an array of size `n` of type `T`
+        template <typename COUNT, typename = DisableIfVectorLike<COUNT>>
+        ast::Type array(ast::Type subtype,
+                        COUNT&& n,
+                        utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
+            return array(builder->source_, subtype, std::forward<COUNT>(n), std::move(attrs));
+        }
+
         /// @param source the Source of the node
         /// @param subtype the array element type
         /// @param n the array size. nullptr represents a runtime-array
@@ -1054,53 +1052,47 @@
 
         /// @param source the Source of the node
         /// @return a inferred-size or runtime-sized array of type `T`
-        template <typename T, typename = EnableIfInferOrAbstract<T>>
+        template <typename T, int N = 0, typename = EnableIfInferOrAbstract<T>>
         ast::Type array(const Source& source) const {
+            static_assert(N == 0, "arrays with a count cannot be inferred");
             return (*this)(source, "array");
         }
 
         /// @return a inferred-size or runtime-sized array of type `T`
-        template <typename T, typename = EnableIfInferOrAbstract<T>>
+        template <typename T, int N = 0, typename = EnableIfInferOrAbstract<T>>
         ast::Type array() const {
+            static_assert(N == 0, "arrays with a count cannot be inferred");
             return array<T>(builder->source_);
         }
 
         /// @param source the Source of the node
         /// @param attrs the optional attributes for the array
         /// @return a inferred-size or runtime-sized array of type `T`
-        template <typename T, typename = DisableIfInferOrAbstract<T>>
+        template <typename T, int N = 0, typename = DisableIfInferOrAbstract<T>>
         ast::Type array(const Source& source,
                         utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
-            return ast::Type{builder->Expr(
-                builder->create<ast::TemplatedIdentifier>(source, builder->Sym("array"),
-                                                          utils::Vector<const ast::Expression*, 1>{
-                                                              Of<T>().expr,
-                                                          },
-                                                          std::move(attrs)))};
-        }
-
-        /// @param attrs the optional attributes for the array
-        /// @return a inferred-size or runtime-sized array of type `T`
-        template <typename T, typename = DisableIfInferOrAbstract<T>>
-        ast::Type array(utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
-            return array<T>(builder->source_, std::move(attrs));
-        }
-
-        /// @param source the Source of the node
-        /// @param attrs the optional attributes for the array
-        /// @return an array of size `N` of type `T`
-        template <typename T, int N>
-        ast::Type array(const Source& source,
-                        utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
-            static_assert(!IsInferOrAbstract<T>, "arrays with a count cannot be inferred");
-            return array(source, Of<T>(), tint::u32(N), std::move(attrs));
+            if constexpr (N == 0) {
+                return ast::Type{builder->Expr(builder->create<ast::TemplatedIdentifier>(
+                    source, builder->Sym("array"),
+                    utils::Vector<const ast::Expression*, 1>{
+                        Of<T>().expr,
+                    },
+                    std::move(attrs)))};
+            } else {
+                return ast::Type{builder->Expr(builder->create<ast::TemplatedIdentifier>(
+                    source, builder->Sym("array"),
+                    utils::Vector{
+                        Of<T>().expr,
+                        builder->Expr(builder->source_, tint::u32(N)),
+                    },
+                    std::move(attrs)))};
+            }
         }
 
         /// @param attrs the optional attributes for the array
         /// @return an array of size `N` of type `T`
-        template <typename T, int N>
+        template <typename T, int N = 0, typename = DisableIfInferOrAbstract<T>>
         ast::Type array(utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
-            static_assert(!IsInferOrAbstract<T>, "arrays with a count cannot be inferred");
             return array<T, N>(builder->source_, std::move(attrs));
         }
 
@@ -1160,9 +1152,48 @@
         }
 
         /// @param source the Source of the node
+        /// @return the pointer to type `T` with the builtin::AddressSpace `ADDRESS` and access
+        /// control `ACCESS`.
+        template <builtin::AddressSpace ADDRESS,
+                  typename T,
+                  builtin::Access ACCESS = builtin::Access::kUndefined>
+        ast::Type ptr(const Source& source) const {
+            return ptr<T>(source, ADDRESS, ACCESS);
+        }
+
+        /// @param type the type of the pointer
+        /// @return the pointer to the given type with the builtin::AddressSpace `ADDRESS` and
+        /// access control `ACCESS`.
+        template <builtin::AddressSpace ADDRESS,
+                  builtin::Access ACCESS = builtin::Access::kUndefined>
+        ast::Type ptr(ast::Type type) const {
+            return ptr(builder->source_, ADDRESS, type, ACCESS);
+        }
+
+        /// @param source the Source of the node
+        /// @param type the type of the pointer
+        /// @return the pointer to the given type with the builtin::AddressSpace `ADDRESS` and
+        /// access control `ACCESS`.
+        template <builtin::AddressSpace ADDRESS,
+                  builtin::Access ACCESS = builtin::Access::kUndefined>
+        ast::Type ptr(const Source& source, ast::Type type) const {
+            return ptr(source, ADDRESS, type, ACCESS);
+        }
+
+        /// @return the pointer to type `T` with the builtin::AddressSpace `ADDRESS` and access
+        /// control `ACCESS`.
+        template <builtin::AddressSpace ADDRESS,
+                  typename T,
+                  builtin::Access ACCESS = builtin::Access::kUndefined>
+        ast::Type ptr() const {
+            return ptr<T>(builder->source_, ADDRESS, ACCESS);
+        }
+
+        /// @param source the Source of the node
         /// @param address_space the address space of the pointer
         /// @param access the optional access control of the pointer
-        /// @return the pointer to type `T` with the given builtin::AddressSpace.
+        /// @return the pointer to type `T` the builtin::AddressSpace `ADDRESS` and access control
+        /// `ACCESS`.
         template <typename T>
         ast::Type ptr(const Source& source,
                       builtin::AddressSpace address_space,
@@ -1654,325 +1685,6 @@
         return Call(source, ty.vec(type, size), std::forward<ARGS>(args)...);
     }
 
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 2-element vector of type `T`, constructed with the
-    /// values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* vec2(ARGS&&... args) {
-        return vec2<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the vector source
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 2-element vector of type `T`, constructed with the
-    /// values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* vec2(const Source& source, ARGS&&... args) {
-        return Call(source, ty.vec2<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param type the element type of the vector
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 2-element vector of type @p type, constructed with the
-    /// values @p args.
-    template <typename... ARGS>
-    const ast::CallExpression* vec2(ast::Type type, ARGS&&... args) {
-        return vec2(source_, type, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the vector source
-    /// @param type the element type of the vector
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 2-element vector of type @p type, constructed with the
-    /// values @p args.
-    template <typename... ARGS>
-    const ast::CallExpression* vec2(const Source& source, ast::Type type, ARGS&&... args) {
-        return Call(source, ty.vec2(type), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 3-element vector of type `T`, constructed with the
-    /// values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* vec3(ARGS&&... args) {
-        return vec3<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the vector source
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 3-element vector of type `T`, constructed with the
-    /// values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* vec3(const Source& source, ARGS&&... args) {
-        return Call(source, ty.vec3<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param type the element type of the vector
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 3-element vector of type @p type, constructed with the
-    /// values @p args.
-    template <typename... ARGS>
-    const ast::CallExpression* vec3(ast::Type type, ARGS&&... args) {
-        return vec3(source_, type, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the vector source
-    /// @param type the element type of the vector
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 3-element vector of type @p type, constructed with the
-    /// values @p args.
-    template <typename... ARGS>
-    const ast::CallExpression* vec3(const Source& source, ast::Type type, ARGS&&... args) {
-        return Call(source, ty.vec3(type), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 4-element vector of type `T`, constructed with the
-    /// values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* vec4(ARGS&&... args) {
-        return vec4<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the vector source
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 4-element vector of type `T`, constructed with the
-    /// values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* vec4(const Source& source, ARGS&&... args) {
-        return Call(source, ty.vec4<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param type the element type of the vector
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 4-element vector of type @p type, constructed with the
-    /// values @p args.
-    template <typename... ARGS>
-    const ast::CallExpression* vec4(ast::Type type, ARGS&&... args) {
-        return vec4(source_, type, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the vector source
-    /// @param type the element type of the vector
-    /// @param args the arguments for the vector constructor
-    /// @return an `ast::CallExpression` of a 4-element vector of type @p type, constructed with the
-    /// values @p args.
-    template <typename... ARGS>
-    const ast::CallExpression* vec4(const Source& source, ast::Type type, ARGS&&... args) {
-        return Call(source, ty.vec4(type), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 2x2 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* mat2x2(ARGS&&... args) {
-        return mat2x2<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the matrix source
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 2x2 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* mat2x2(const Source& source, ARGS&&... args) {
-        return Call(source, ty.mat2x2<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 2x3 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* mat2x3(ARGS&&... args) {
-        return mat2x3<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the matrix source
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 2x3 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* mat2x3(const Source& source, ARGS&&... args) {
-        return Call(source, ty.mat2x3<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 2x4 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* mat2x4(ARGS&&... args) {
-        return mat2x4<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the matrix source
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 2x4 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* mat2x4(const Source& source, ARGS&&... args) {
-        return Call(source, ty.mat2x4<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 3x2 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* mat3x2(ARGS&&... args) {
-        return mat3x2<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the matrix source
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 3x2 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* mat3x2(const Source& source, ARGS&&... args) {
-        return Call(source, ty.mat3x2<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 3x3 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* mat3x3(ARGS&&... args) {
-        return mat3x3<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the matrix source
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 3x3 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* mat3x3(const Source& source, ARGS&&... args) {
-        return Call(source, ty.mat3x3<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 3x4 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* mat3x4(ARGS&&... args) {
-        return mat3x4<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the matrix source
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 3x4 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* mat3x4(const Source& source, ARGS&&... args) {
-        return Call(source, ty.mat3x4<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 4x2 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* mat4x2(ARGS&&... args) {
-        return mat4x2<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the matrix source
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 4x2 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* mat4x2(const Source& source, ARGS&&... args) {
-        return Call(source, ty.mat4x2<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 4x3 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* mat4x3(ARGS&&... args) {
-        return mat4x3<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the matrix source
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 4x3 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* mat4x3(const Source& source, ARGS&&... args) {
-        return Call(source, ty.mat4x3<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 4x4 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* mat4x4(ARGS&&... args) {
-        return mat4x4<T>(source_, std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the matrix source
-    /// @param args the arguments for the matrix constructor
-    /// @return an `ast::CallExpression` of a 4x4 matrix of type
-    /// `T`, constructed with the values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* mat4x4(const Source& source, ARGS&&... args) {
-        return Call(source, ty.mat4x4<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the array constructor
-    /// @return an `ast::CallExpression` of an array with element type `T`, constructed with the
-    /// values @p args.
-    template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* array(ARGS&&... args) {
-        return Call(ty.array<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the array source
-    /// @param args the arguments for the array constructor
-    /// @return an `ast::CallExpression` of an array with element type `T`, constructed with the
-    /// values @p args.
-    template <typename T, typename... ARGS>
-    const ast::CallExpression* array(const Source& source, ARGS&&... args) {
-        return Call(source, ty.array<T>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param args the arguments for the array constructor
-    /// @return an `ast::CallExpression` of an array with element type `T` and size `N`, constructed
-    /// with the values @p args.
-    template <typename T, int N, typename... ARGS, typename = DisableIfSource<ARGS...>>
-    const ast::CallExpression* array(ARGS&&... args) {
-        return Call(ty.array<T, N>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the array source
-    /// @param args the arguments for the array constructor
-    /// @return an `ast::CallExpression` of an array with element type `T` and size `N`, constructed
-    /// with the values @p args.
-    template <typename T, int N, typename... ARGS>
-    const ast::CallExpression* array(const Source& source, ARGS&&... args) {
-        return Call(source, ty.array<T, N>(), std::forward<ARGS>(args)...);
-    }
-
-    /// @param subtype the array element type
-    /// @param n the array size. nullptr represents a runtime-array.
-    /// @param args the arguments for the array constructor
-    /// @return an `ast::CallExpression` of an array with element type
-    /// `subtype`, constructed with the values @p args.
-    template <typename EXPR, typename... ARGS>
-    const ast::CallExpression* array(ast::Type subtype, EXPR&& n, ARGS&&... args) {
-        return Call(ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
-    }
-
-    /// @param source the array source
-    /// @param subtype the array element type
-    /// @param n the array size. nullptr represents a runtime-array.
-    /// @param args the arguments for the array constructor
-    /// @return an `ast::CallExpression` of an array with element type
-    /// `subtype`, constructed with the values @p args.
-    template <typename EXPR, typename... ARGS>
-    const ast::CallExpression* array(const Source& source,
-                                     ast::Type subtype,
-                                     EXPR&& n,
-                                     ARGS&&... args) {
-        return Call(source, ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
-    }
-
     /// Adds the extension to the list of enable directives at the top of the module.
     /// @param extension the extension to enable
     /// @return an `ast::Enable` enabling the given extension.
@@ -3933,6 +3645,28 @@
 struct ProgramBuilder::TypesBuilder::CToAST<bool> {
     static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->bool_(); }
 };
+template <typename T, uint32_t N>
+struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::array<T, N>> {
+    static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->array<T, N>(); }
+};
+template <typename T>
+struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::atomic<T>> {
+    static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->atomic<T>(); }
+};
+template <uint32_t C, uint32_t R, typename T>
+struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::mat<C, R, T>> {
+    static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->mat<T>(C, R); }
+};
+template <uint32_t N, typename T>
+struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::vec<N, T>> {
+    static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->vec<T, N>(); }
+};
+template <builtin::AddressSpace ADDRESS, typename T, builtin::Access ACCESS>
+struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::ptr<ADDRESS, T, ACCESS>> {
+    static ast::Type get(const ProgramBuilder::TypesBuilder* t) {
+        return t->ptr<ADDRESS, T, ACCESS>();
+    }
+};
 //! @endcond
 
 /// @param builder the ProgramBuilder