ast: Remove ConstructorExpression

ConstructorExpression is abstract, and now only has a single class deriving
from it - TypeConstructorExpression. Just use that instead.

Bug: tint:888
Change-Id: I7ee52ad645bcd8a8a68710c63a1fdf834b5b2a24
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/68842
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 2dc31b8..db0f44d 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -208,8 +208,6 @@
     "ast/call_statement.h",
     "ast/case_statement.cc",
     "ast/case_statement.h",
-    "ast/constructor_expression.cc",
-    "ast/constructor_expression.h",
     "ast/continue_statement.cc",
     "ast/continue_statement.h",
     "ast/decoration.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 50090cd..d1a41c1 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -74,8 +74,6 @@
   ast/call_statement.h
   ast/case_statement.cc
   ast/case_statement.h
-  ast/constructor_expression.cc
-  ast/constructor_expression.h
   ast/continue_statement.cc
   ast/continue_statement.h
   ast/decoration.cc
diff --git a/src/ast/constructor_expression.cc b/src/ast/constructor_expression.cc
deleted file mode 100644
index e1a8224..0000000
--- a/src/ast/constructor_expression.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2020 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "src/ast/constructor_expression.h"
-
-TINT_INSTANTIATE_TYPEINFO(tint::ast::ConstructorExpression);
-
-namespace tint {
-namespace ast {
-
-ConstructorExpression::~ConstructorExpression() = default;
-
-ConstructorExpression::ConstructorExpression(ConstructorExpression&&) = default;
-
-ConstructorExpression::ConstructorExpression(ProgramID pid, const Source& src)
-    : Base(pid, src) {}
-
-}  // namespace ast
-}  // namespace tint
diff --git a/src/ast/constructor_expression.h b/src/ast/constructor_expression.h
deleted file mode 100644
index fc19e98..0000000
--- a/src/ast/constructor_expression.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2020 The Tint Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef SRC_AST_CONSTRUCTOR_EXPRESSION_H_
-#define SRC_AST_CONSTRUCTOR_EXPRESSION_H_
-
-#include "src/ast/expression.h"
-
-namespace tint {
-namespace ast {
-
-/// Base class for constructor style expressions
-class ConstructorExpression
-    : public Castable<ConstructorExpression, Expression> {
- public:
-  ~ConstructorExpression() override;
-
- protected:
-  /// Constructor
-  /// @param pid the identifier of the program that owns this node
-  /// @param src the source of this node
-  ConstructorExpression(ProgramID pid, const Source& src);
-  /// Move constructor
-  ConstructorExpression(ConstructorExpression&&);
-};
-
-}  // namespace ast
-}  // namespace tint
-
-#endif  // SRC_AST_CONSTRUCTOR_EXPRESSION_H_
diff --git a/src/ast/type_constructor_expression.h b/src/ast/type_constructor_expression.h
index 94095e1..d6ed7b5 100644
--- a/src/ast/type_constructor_expression.h
+++ b/src/ast/type_constructor_expression.h
@@ -17,7 +17,7 @@
 
 #include <utility>
 
-#include "src/ast/constructor_expression.h"
+#include "src/ast/expression.h"
 
 namespace tint {
 namespace ast {
@@ -27,7 +27,7 @@
 
 /// A type specific constructor
 class TypeConstructorExpression
-    : public Castable<TypeConstructorExpression, ConstructorExpression> {
+    : public Castable<TypeConstructorExpression, Expression> {
  public:
   /// Constructor
   /// @param pid the identifier of the program that owns this node
diff --git a/src/reader/wgsl/parser_impl_const_expr_test.cc b/src/reader/wgsl/parser_impl_const_expr_test.cc
index 62e5e3f..baf5823 100644
--- a/src/reader/wgsl/parser_impl_const_expr_test.cc
+++ b/src/reader/wgsl/parser_impl_const_expr_test.cc
@@ -24,7 +24,6 @@
   auto e = p->expect_const_expr();
   ASSERT_FALSE(p->has_error()) << p->error();
   ASSERT_FALSE(e.errored);
-  ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 
   auto* t = e->As<ast::TypeConstructorExpression>();
@@ -46,7 +45,6 @@
   auto e = p->expect_const_expr();
   ASSERT_FALSE(p->has_error()) << p->error();
   ASSERT_FALSE(e.errored);
-  ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 
   auto* t = e->As<ast::TypeConstructorExpression>();
@@ -61,7 +59,6 @@
   auto e = p->expect_const_expr();
   ASSERT_FALSE(p->has_error()) << p->error();
   ASSERT_FALSE(e.errored);
-  ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 
   auto* t = e->As<ast::TypeConstructorExpression>();
@@ -137,7 +134,6 @@
 
   auto e = p->expect_const_expr();
   ASSERT_FALSE(e.errored);
-  ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 }
 
diff --git a/src/reader/wgsl/parser_impl_primary_expression_test.cc b/src/reader/wgsl/parser_impl_primary_expression_test.cc
index 1d44f16..e364e5a 100644
--- a/src/reader/wgsl/parser_impl_primary_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_primary_expression_test.cc
@@ -39,7 +39,6 @@
   EXPECT_FALSE(e.errored);
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
-  ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
   auto* ty = e->As<ast::TypeConstructorExpression>();
 
@@ -65,7 +64,6 @@
   EXPECT_FALSE(e.errored);
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
-  ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
   auto* ty = e->As<ast::TypeConstructorExpression>();
 
@@ -227,7 +225,6 @@
   EXPECT_FALSE(e.errored);
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
-  ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 
   auto* c = e->As<ast::TypeConstructorExpression>();
diff --git a/src/reader/wgsl/parser_impl_variable_stmt_test.cc b/src/reader/wgsl/parser_impl_variable_stmt_test.cc
index 39e5e62..5a6653d 100644
--- a/src/reader/wgsl/parser_impl_variable_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_stmt_test.cc
@@ -90,7 +90,7 @@
   EXPECT_EQ(e->variable->symbol, p->builder().Symbols().Get("a"));
 
   ASSERT_NE(e->variable->constructor, nullptr);
-  EXPECT_TRUE(e->variable->constructor->Is<ast::ConstructorExpression>());
+  EXPECT_TRUE(e->variable->constructor->Is<ast::TypeConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, VariableStmt_VariableDecl_ArrayInit_NoSpace) {
@@ -105,7 +105,7 @@
   EXPECT_EQ(e->variable->symbol, p->builder().Symbols().Get("a"));
 
   ASSERT_NE(e->variable->constructor, nullptr);
-  EXPECT_TRUE(e->variable->constructor->Is<ast::ConstructorExpression>());
+  EXPECT_TRUE(e->variable->constructor->Is<ast::TypeConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, VariableStmt_VariableDecl_VecInit) {
@@ -120,7 +120,7 @@
   EXPECT_EQ(e->variable->symbol, p->builder().Symbols().Get("a"));
 
   ASSERT_NE(e->variable->constructor, nullptr);
-  EXPECT_TRUE(e->variable->constructor->Is<ast::ConstructorExpression>());
+  EXPECT_TRUE(e->variable->constructor->Is<ast::TypeConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, VariableStmt_VariableDecl_VecInit_NoSpace) {
@@ -135,7 +135,7 @@
   EXPECT_EQ(e->variable->symbol, p->builder().Symbols().Get("a"));
 
   ASSERT_NE(e->variable->constructor, nullptr);
-  EXPECT_TRUE(e->variable->constructor->Is<ast::ConstructorExpression>());
+  EXPECT_TRUE(e->variable->constructor->Is<ast::TypeConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, VariableStmt_Let) {
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc
index 6943354..25bcd44 100644
--- a/src/resolver/resolver.cc
+++ b/src/resolver/resolver.cc
@@ -2362,8 +2362,8 @@
       sem_expr = Bitcast(bitcast);
     } else if (auto* call = expr->As<ast::CallExpression>()) {
       sem_expr = Call(call);
-    } else if (auto* ctor = expr->As<ast::ConstructorExpression>()) {
-      sem_expr = Constructor(ctor);
+    } else if (auto* ctor = expr->As<ast::TypeConstructorExpression>()) {
+      sem_expr = TypeConstructor(ctor);
     } else if (auto* ident = expr->As<ast::IdentifierExpression>()) {
       sem_expr = Identifier(ident);
     } else if (auto* literal = expr->As<ast::Literal>()) {
@@ -2730,41 +2730,37 @@
   return true;
 }
 
-sem::Expression* Resolver::Constructor(const ast::ConstructorExpression* expr) {
-  if (auto* type_ctor = expr->As<ast::TypeConstructorExpression>()) {
-    auto* ty = Type(type_ctor->type);
-    if (!ty) {
-      return nullptr;
-    }
-
-    // Now that the argument types have been determined, make sure that they
-    // obey the constructor type rules laid out in
-    // https://gpuweb.github.io/gpuweb/wgsl.html#type-constructor-expr.
-    bool ok = true;
-    if (auto* vec_type = ty->As<sem::Vector>()) {
-      ok = ValidateVectorConstructor(type_ctor, vec_type);
-    } else if (auto* mat_type = ty->As<sem::Matrix>()) {
-      ok = ValidateMatrixConstructor(type_ctor, mat_type);
-    } else if (ty->is_scalar()) {
-      ok = ValidateScalarConstructor(type_ctor, ty);
-    } else if (auto* arr_type = ty->As<sem::Array>()) {
-      ok = ValidateArrayConstructor(type_ctor, arr_type);
-    } else if (auto* struct_type = ty->As<sem::Struct>()) {
-      ok = ValidateStructureConstructor(type_ctor, struct_type);
-    } else {
-      AddError("type is not constructible", type_ctor->source);
-      return nullptr;
-    }
-    if (!ok) {
-      return nullptr;
-    }
-
-    auto val = EvaluateConstantValue(expr, ty);
-    return builder_->create<sem::Expression>(expr, ty, current_statement_, val);
+sem::Expression* Resolver::TypeConstructor(
+    const ast::TypeConstructorExpression* expr) {
+  auto* ty = Type(expr->type);
+  if (!ty) {
+    return nullptr;
   }
 
-  TINT_ICE(Resolver, diagnostics_) << "unexpected constructor expression type";
-  return nullptr;
+  // Now that the argument types have been determined, make sure that they
+  // obey the constructor type rules laid out in
+  // https://gpuweb.github.io/gpuweb/wgsl.html#type-constructor-expr.
+  bool ok = true;
+  if (auto* vec_type = ty->As<sem::Vector>()) {
+    ok = ValidateVectorConstructor(expr, vec_type);
+  } else if (auto* mat_type = ty->As<sem::Matrix>()) {
+    ok = ValidateMatrixConstructor(expr, mat_type);
+  } else if (ty->is_scalar()) {
+    ok = ValidateScalarConstructor(expr, ty);
+  } else if (auto* arr_type = ty->As<sem::Array>()) {
+    ok = ValidateArrayConstructor(expr, arr_type);
+  } else if (auto* struct_type = ty->As<sem::Struct>()) {
+    ok = ValidateStructureConstructor(expr, struct_type);
+  } else {
+    AddError("type is not constructible", expr->source);
+    return nullptr;
+  }
+  if (!ok) {
+    return nullptr;
+  }
+
+  auto val = EvaluateConstantValue(expr, ty);
+  return builder_->create<sem::Expression>(expr, ty, current_statement_, val);
 }
 
 sem::Expression* Resolver::Literal(const ast::Literal* literal) {
diff --git a/src/resolver/resolver.h b/src/resolver/resolver.h
index c19dfee..b6c5118 100644
--- a/src/resolver/resolver.h
+++ b/src/resolver/resolver.h
@@ -171,7 +171,6 @@
   sem::Expression* Binary(const ast::BinaryExpression*);
   sem::Expression* Bitcast(const ast::BitcastExpression*);
   sem::Expression* Call(const ast::CallExpression*);
-  sem::Expression* Constructor(const ast::ConstructorExpression*);
   sem::Expression* Expression(const ast::Expression*);
   sem::Function* Function(const ast::Function*);
   sem::Call* FunctionCall(const ast::CallExpression*);
@@ -179,6 +178,7 @@
   sem::Call* IntrinsicCall(const ast::CallExpression*, sem::IntrinsicType);
   sem::Expression* Literal(const ast::Literal*);
   sem::Expression* MemberAccessor(const ast::MemberAccessorExpression*);
+  sem::Expression* TypeConstructor(const ast::TypeConstructorExpression*);
   sem::Expression* UnaryOp(const ast::UnaryOpExpression*);
 
   // Statement resolving methods
diff --git a/src/writer/glsl/generator_impl.cc b/src/writer/glsl/generator_impl.cc
index 1d0213a..7f26088 100644
--- a/src/writer/glsl/generator_impl.cc
+++ b/src/writer/glsl/generator_impl.cc
@@ -1385,11 +1385,6 @@
   return true;
 }
 
-bool GeneratorImpl::EmitConstructor(std::ostream& out,
-                                    const ast::ConstructorExpression* expr) {
-  return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
-}
-
 bool GeneratorImpl::EmitTypeConstructor(
     std::ostream& out,
     const ast::TypeConstructorExpression* expr) {
@@ -1471,8 +1466,8 @@
   if (auto* c = expr->As<ast::CallExpression>()) {
     return EmitCall(out, c);
   }
-  if (auto* c = expr->As<ast::ConstructorExpression>()) {
-    return EmitConstructor(out, c);
+  if (auto* c = expr->As<ast::TypeConstructorExpression>()) {
+    return EmitTypeConstructor(out, c);
   }
   if (auto* i = expr->As<ast::IdentifierExpression>()) {
     return EmitIdentifier(out, i);
diff --git a/src/writer/glsl/generator_impl.h b/src/writer/glsl/generator_impl.h
index c478d3b..8d6a4f5 100644
--- a/src/writer/glsl/generator_impl.h
+++ b/src/writer/glsl/generator_impl.h
@@ -188,12 +188,6 @@
   /// @param stmt the statement
   /// @returns true if the statement was emitted successfully
   bool EmitCase(const ast::CaseStatement* stmt);
-  /// Handles generating constructor expressions
-  /// @param out the output of the expression stream
-  /// @param expr the constructor expression
-  /// @returns true if the expression was emitted
-  bool EmitConstructor(std::ostream& out,
-                       const ast::ConstructorExpression* expr);
   /// Handles generating a discard statement
   /// @param stmt the discard statement
   /// @returns true if the statement was successfully emitted
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index 8a2d114..92fe82e 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -2112,11 +2112,6 @@
   return true;
 }
 
-bool GeneratorImpl::EmitConstructor(std::ostream& out,
-                                    const ast::ConstructorExpression* expr) {
-  return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
-}
-
 bool GeneratorImpl::EmitTypeConstructor(
     std::ostream& out,
     const ast::TypeConstructorExpression* expr) {
@@ -2203,8 +2198,8 @@
   if (auto* c = expr->As<ast::CallExpression>()) {
     return EmitCall(out, c);
   }
-  if (auto* c = expr->As<ast::ConstructorExpression>()) {
-    return EmitConstructor(out, c);
+  if (auto* c = expr->As<ast::TypeConstructorExpression>()) {
+    return EmitTypeConstructor(out, c);
   }
   if (auto* i = expr->As<ast::IdentifierExpression>()) {
     return EmitIdentifier(out, i);
diff --git a/src/writer/hlsl/generator_impl.h b/src/writer/hlsl/generator_impl.h
index 1aadf4a..1945d4e 100644
--- a/src/writer/hlsl/generator_impl.h
+++ b/src/writer/hlsl/generator_impl.h
@@ -217,12 +217,6 @@
   /// @param case_idx the index of the switch case in the switch statement
   /// @returns true if the statement was emitted successfully
   bool EmitCase(const ast::SwitchStatement* s, size_t case_idx);
-  /// Handles generating constructor expressions
-  /// @param out the output of the expression stream
-  /// @param expr the constructor expression
-  /// @returns true if the expression was emitted
-  bool EmitConstructor(std::ostream& out,
-                       const ast::ConstructorExpression* expr);
   /// Handles generating a discard statement
   /// @param stmt the discard statement
   /// @returns true if the statement was successfully emitted
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index f733b27..a981b8a 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -1291,11 +1291,6 @@
   return true;
 }
 
-bool GeneratorImpl::EmitConstructor(std::ostream& out,
-                                    const ast::ConstructorExpression* expr) {
-  return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
-}
-
 bool GeneratorImpl::EmitContinue(const ast::ContinueStatement*) {
   if (!emit_continuing_()) {
     return false;
@@ -1430,8 +1425,8 @@
   if (auto* c = expr->As<ast::CallExpression>()) {
     return EmitCall(out, c);
   }
-  if (auto* c = expr->As<ast::ConstructorExpression>()) {
-    return EmitConstructor(out, c);
+  if (auto* c = expr->As<ast::TypeConstructorExpression>()) {
+    return EmitTypeConstructor(out, c);
   }
   if (auto* i = expr->As<ast::IdentifierExpression>()) {
     return EmitIdentifier(out, i);
diff --git a/src/writer/msl/generator_impl.h b/src/writer/msl/generator_impl.h
index 557c941..58cfe38 100644
--- a/src/writer/msl/generator_impl.h
+++ b/src/writer/msl/generator_impl.h
@@ -182,12 +182,6 @@
   /// @param stmt the statement
   /// @returns true if the statement was emitted successfully
   bool EmitCase(const ast::CaseStatement* stmt);
-  /// Handles generating constructor expressions
-  /// @param out the output of the expression stream
-  /// @param expr the constructor expression
-  /// @returns true if the expression was emitted
-  bool EmitConstructor(std::ostream& out,
-                       const ast::ConstructorExpression* expr);
   /// Handles a continue statement
   /// @param stmt the statement to emit
   /// @returns true if the statement was emitted successfully
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 75d4d0d..4d06377 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -577,7 +577,7 @@
   if (auto* c = expr->As<ast::CallExpression>()) {
     return GenerateCallExpression(c);
   }
-  if (auto* c = expr->As<ast::ConstructorExpression>()) {
+  if (auto* c = expr->As<ast::TypeConstructorExpression>()) {
     return GenerateConstructorExpression(nullptr, c);
   }
   if (auto* i = expr->As<ast::IdentifierExpression>()) {
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index 97ff2ff..cf4bd4c 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -134,8 +134,8 @@
   if (auto* l = expr->As<ast::Literal>()) {
     return EmitLiteral(out, l);
   }
-  if (auto* c = expr->As<ast::ConstructorExpression>()) {
-    return EmitConstructor(out, c);
+  if (auto* c = expr->As<ast::TypeConstructorExpression>()) {
+    return EmitTypeConstructor(out, c);
   }
   if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
     return EmitMemberAccessor(out, m);
@@ -243,11 +243,6 @@
   return true;
 }
 
-bool GeneratorImpl::EmitConstructor(std::ostream& out,
-                                    const ast::ConstructorExpression* expr) {
-  return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
-}
-
 bool GeneratorImpl::EmitTypeConstructor(
     std::ostream& out,
     const ast::TypeConstructorExpression* expr) {
diff --git a/src/writer/wgsl/generator_impl.h b/src/writer/wgsl/generator_impl.h
index 5a8559e..b1d83b3 100644
--- a/src/writer/wgsl/generator_impl.h
+++ b/src/writer/wgsl/generator_impl.h
@@ -120,18 +120,12 @@
   /// Handles generating an identifier expression
   /// @param out the output of the expression stream
   /// @param expr the identifier expression
-  /// @returns true if the identifeir was emitted
+  /// @returns true if the identifier was emitted
   bool EmitIdentifier(std::ostream& out, const ast::IdentifierExpression* expr);
   /// Handles an if statement
   /// @param stmt the statement to emit
   /// @returns true if the statement was successfully emitted
   bool EmitIf(const ast::IfStatement* stmt);
-  /// Handles generating constructor expressions
-  /// @param out the output of the expression stream
-  /// @param expr the constructor expression
-  /// @returns true if the expression was emitted
-  bool EmitConstructor(std::ostream& out,
-                       const ast::ConstructorExpression* expr);
   /// Handles generating a discard statement
   /// @param stmt the discard statement
   /// @returns true if the statement was successfully emitted