diff --git a/src/ast/else_statement.cc b/src/ast/else_statement.cc
index e430571d51..15891ceef1 100644
--- a/src/ast/else_statement.cc
+++ b/src/ast/else_statement.cc
@@ -17,21 +17,45 @@
 namespace tint {
 namespace ast {
 
-ElseStatement::ElseStatement() : Statement() {}
+ElseStatement::ElseStatement()
+    : Statement(), body_(std::make_unique<ast::BlockStatement>()) {}
 
-ElseStatement::ElseStatement(StatementList body)
+ElseStatement::ElseStatement(std::unique_ptr<BlockStatement> body)
     : Statement(), body_(std::move(body)) {}
 
 ElseStatement::ElseStatement(std::unique_ptr<Expression> condition,
                              StatementList body)
+    : Statement(),
+      condition_(std::move(condition)),
+      body_(std::make_unique<BlockStatement>()) {
+  set_body(std::move(body));
+}
+
+ElseStatement::ElseStatement(std::unique_ptr<Expression> condition,
+                             std::unique_ptr<BlockStatement> body)
     : Statement(), condition_(std::move(condition)), body_(std::move(body)) {}
 
 ElseStatement::ElseStatement(const Source& source, StatementList body)
+    : Statement(source), body_(std::make_unique<BlockStatement>()) {
+  set_body(std::move(body));
+}
+
+ElseStatement::ElseStatement(const Source& source,
+                             std::unique_ptr<BlockStatement> body)
     : Statement(source), body_(std::move(body)) {}
 
 ElseStatement::ElseStatement(const Source& source,
                              std::unique_ptr<Expression> condition,
                              StatementList body)
+    : Statement(source),
+      condition_(std::move(condition)),
+      body_(std::make_unique<BlockStatement>()) {
+  set_body(std::move(body));
+}
+
+ElseStatement::ElseStatement(const Source& source,
+                             std::unique_ptr<Expression> condition,
+                             std::unique_ptr<BlockStatement> body)
     : Statement(source),
       condition_(std::move(condition)),
       body_(std::move(body)) {}
@@ -40,19 +64,21 @@ ElseStatement::ElseStatement(ElseStatement&&) = default;
 
 ElseStatement::~ElseStatement() = default;
 
+void ElseStatement::set_body(StatementList body) {
+  for (auto& stmt : body) {
+    body_->append(std::move(stmt));
+  }
+}
+
 bool ElseStatement::IsElse() const {
   return true;
 }
 
 bool ElseStatement::IsValid() const {
-  for (const auto& stmt : body_) {
-    if (stmt == nullptr || !stmt->IsValid())
-      return false;
+  if (body_ == nullptr || !body_->IsValid()) {
+    return false;
   }
-  if (condition_)
-    return condition_->IsValid();
-
-  return true;
+  return condition_ == nullptr || condition_->IsValid();
 }
 
 void ElseStatement::to_str(std::ostream& out, size_t indent) const {
@@ -71,8 +97,11 @@ void ElseStatement::to_str(std::ostream& out, size_t indent) const {
   make_indent(out, indent + 2);
   out << "{" << std::endl;
 
-  for (const auto& stmt : body_)
-    stmt->to_str(out, indent + 4);
+  if (body_ != nullptr) {
+    for (const auto& stmt : *body_) {
+      stmt->to_str(out, indent + 4);
+    }
+  }
 
   make_indent(out, indent + 2);
   out << "}" << std::endl;
diff --git a/src/ast/else_statement.h b/src/ast/else_statement.h
index b627769da8..d0e0cf7403 100644
--- a/src/ast/else_statement.h
+++ b/src/ast/else_statement.h
@@ -19,6 +19,7 @@
 #include <utility>
 #include <vector>
 
+#include "src/ast/block_statement.h"
 #include "src/ast/expression.h"
 #include "src/ast/statement.h"
 
@@ -32,22 +33,38 @@ class ElseStatement : public Statement {
   ElseStatement();
   /// Constructor
   /// @param body the else body
-  explicit ElseStatement(StatementList body);
+  explicit ElseStatement(std::unique_ptr<BlockStatement> body);
   /// Constructor
   /// @param condition the else condition
   /// @param body the else body
   ElseStatement(std::unique_ptr<Expression> condition, StatementList body);
   /// Constructor
+  /// @param condition the else condition
+  /// @param body the else body
+  ElseStatement(std::unique_ptr<Expression> condition,
+                std::unique_ptr<BlockStatement> body);
+  /// Constructor
   /// @param source the source information
   /// @param body the else body
   ElseStatement(const Source& source, StatementList body);
   /// Constructor
   /// @param source the source information
+  /// @param body the else body
+  ElseStatement(const Source& source, std::unique_ptr<BlockStatement> body);
+  /// Constructor
+  /// @param source the source information
   /// @param condition the else condition
   /// @param body the else body
   ElseStatement(const Source& source,
                 std::unique_ptr<Expression> condition,
                 StatementList body);
+  /// Constructor
+  /// @param source the source information
+  /// @param condition the else condition
+  /// @param body the else body
+  ElseStatement(const Source& source,
+                std::unique_ptr<Expression> condition,
+                std::unique_ptr<BlockStatement> body);
   /// Move constructor
   ElseStatement(ElseStatement&&);
   ~ElseStatement() override;
@@ -64,9 +81,11 @@ class ElseStatement : public Statement {
 
   /// Sets the else body
   /// @param body the else body
-  void set_body(StatementList body) { body_ = std::move(body); }
+  void set_body(std::unique_ptr<BlockStatement> body) {
+    body_ = std::move(body);
+  }
   /// @returns the else body
-  const StatementList& body() const { return body_; }
+  const BlockStatement* body() const { return body_.get(); }
 
   /// @returns true if this is a else statement
   bool IsElse() const override;
@@ -82,8 +101,12 @@ class ElseStatement : public Statement {
  private:
   ElseStatement(const ElseStatement&) = delete;
 
+  /// Sets the else body
+  /// @param body the else body
+  void set_body(StatementList body);
+
   std::unique_ptr<Expression> condition_;
-  StatementList body_;
+  std::unique_ptr<BlockStatement> body_;
 };
 
 /// A list of unique else statements
diff --git a/src/ast/else_statement_test.cc b/src/ast/else_statement_test.cc
index 9b729e89b2..d791ad0a0f 100644
--- a/src/ast/else_statement_test.cc
+++ b/src/ast/else_statement_test.cc
@@ -31,20 +31,20 @@ TEST_F(ElseStatementTest, Creation) {
   ast::type::BoolType bool_type;
   auto cond = std::make_unique<ScalarConstructorExpression>(
       std::make_unique<BoolLiteral>(&bool_type, true));
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   auto* cond_ptr = cond.get();
-  auto* discard_ptr = body[0].get();
+  auto* discard_ptr = body->get(0);
 
   ElseStatement e(std::move(cond), std::move(body));
   EXPECT_EQ(e.condition(), cond_ptr);
-  ASSERT_EQ(e.body().size(), 1u);
-  EXPECT_EQ(e.body()[0].get(), discard_ptr);
+  ASSERT_EQ(e.body()->size(), 1u);
+  EXPECT_EQ(e.body()->get(0), discard_ptr);
 }
 
 TEST_F(ElseStatementTest, Creation_WithSource) {
-  ElseStatement e(Source{20, 2}, {});
+  ElseStatement e(Source{20, 2}, std::make_unique<BlockStatement>());
   auto src = e.source();
   EXPECT_EQ(src.line, 20u);
   EXPECT_EQ(src.column, 2u);
@@ -59,7 +59,7 @@ TEST_F(ElseStatementTest, HasCondition) {
   ast::type::BoolType bool_type;
   auto cond = std::make_unique<ScalarConstructorExpression>(
       std::make_unique<BoolLiteral>(&bool_type, true));
-  ElseStatement e(std::move(cond), {});
+  ElseStatement e(std::move(cond), std::make_unique<BlockStatement>());
   EXPECT_TRUE(e.HasCondition());
 }
 
@@ -74,17 +74,17 @@ TEST_F(ElseStatementTest, IsValid) {
 }
 
 TEST_F(ElseStatementTest, IsValid_WithBody) {
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   ElseStatement e(std::move(body));
   EXPECT_TRUE(e.IsValid());
 }
 
 TEST_F(ElseStatementTest, IsValid_WithNullBodyStatement) {
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
-  body.push_back(nullptr);
+  auto body = std::make_unique<BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
+  body->append(nullptr);
 
   ElseStatement e(std::move(body));
   EXPECT_FALSE(e.IsValid());
@@ -92,13 +92,13 @@ TEST_F(ElseStatementTest, IsValid_WithNullBodyStatement) {
 
 TEST_F(ElseStatementTest, IsValid_InvalidCondition) {
   auto cond = std::make_unique<ScalarConstructorExpression>();
-  ElseStatement e(std::move(cond), {});
+  ElseStatement e(std::move(cond), std::make_unique<BlockStatement>());
   EXPECT_FALSE(e.IsValid());
 }
 
 TEST_F(ElseStatementTest, IsValid_InvalidBodyStatement) {
-  StatementList body;
-  body.push_back(std::make_unique<IfStatement>());
+  auto body = std::make_unique<BlockStatement>();
+  body->append(std::make_unique<IfStatement>());
 
   ElseStatement e(std::move(body));
   EXPECT_FALSE(e.IsValid());
@@ -108,8 +108,8 @@ TEST_F(ElseStatementTest, ToStr) {
   ast::type::BoolType bool_type;
   auto cond = std::make_unique<ScalarConstructorExpression>(
       std::make_unique<BoolLiteral>(&bool_type, true));
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   ElseStatement e(std::move(cond), std::move(body));
   std::ostringstream out;
@@ -126,8 +126,8 @@ TEST_F(ElseStatementTest, ToStr) {
 }
 
 TEST_F(ElseStatementTest, ToStr_NoCondition) {
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   ElseStatement e(std::move(body));
   std::ostringstream out;
diff --git a/src/ast/if_statement.cc b/src/ast/if_statement.cc
index 3fc380864d..342c08f01a 100644
--- a/src/ast/if_statement.cc
+++ b/src/ast/if_statement.cc
@@ -19,15 +19,25 @@
 namespace tint {
 namespace ast {
 
-IfStatement::IfStatement() : Statement() {}
+IfStatement::IfStatement()
+    : Statement(), body_(std::make_unique<BlockStatement>()) {}
 
 IfStatement::IfStatement(std::unique_ptr<Expression> condition,
-                         StatementList body)
+                         std::unique_ptr<BlockStatement> body)
     : Statement(), condition_(std::move(condition)), body_(std::move(body)) {}
 
 IfStatement::IfStatement(const Source& source,
                          std::unique_ptr<Expression> condition,
                          StatementList body)
+    : Statement(source),
+      condition_(std::move(condition)),
+      body_(std::make_unique<BlockStatement>()) {
+  set_body(std::move(body));
+}
+
+IfStatement::IfStatement(const Source& source,
+                         std::unique_ptr<Expression> condition,
+                         std::unique_ptr<BlockStatement> body)
     : Statement(source),
       condition_(std::move(condition)),
       body_(std::move(body)) {}
@@ -36,17 +46,22 @@ IfStatement::IfStatement(IfStatement&&) = default;
 
 IfStatement::~IfStatement() = default;
 
+void IfStatement::set_body(StatementList body) {
+  for (auto& stmt : body) {
+    body_->append(std::move(stmt));
+  }
+}
+
 bool IfStatement::IsIf() const {
   return true;
 }
 
 bool IfStatement::IsValid() const {
-  if (condition_ == nullptr || !condition_->IsValid())
+  if (condition_ == nullptr || !condition_->IsValid()) {
+    return false;
+  }
+  if (body_ == nullptr || !body_->IsValid()) {
     return false;
-
-  for (const auto& stmt : body_) {
-    if (stmt == nullptr || !stmt->IsValid())
-      return false;
   }
 
   bool found_else = false;
@@ -83,8 +98,11 @@ void IfStatement::to_str(std::ostream& out, size_t indent) const {
   make_indent(out, indent + 2);
   out << "{" << std::endl;
 
-  for (const auto& stmt : body_)
-    stmt->to_str(out, indent + 4);
+  if (body_ != nullptr) {
+    for (const auto& stmt : *body_) {
+      stmt->to_str(out, indent + 4);
+    }
+  }
 
   // Close the if body
   make_indent(out, indent + 2);
diff --git a/src/ast/if_statement.h b/src/ast/if_statement.h
index 3ee40f85e1..8db80e5da6 100644
--- a/src/ast/if_statement.h
+++ b/src/ast/if_statement.h
@@ -18,6 +18,7 @@
 #include <memory>
 #include <utility>
 
+#include "src/ast/block_statement.h"
 #include "src/ast/else_statement.h"
 #include "src/ast/expression.h"
 #include "src/ast/statement.h"
@@ -33,7 +34,8 @@ class IfStatement : public Statement {
   /// Constructor
   /// @param condition the if condition
   /// @param body the if body
-  IfStatement(std::unique_ptr<Expression> condition, StatementList body);
+  IfStatement(std::unique_ptr<Expression> condition,
+              std::unique_ptr<BlockStatement> body);
   /// Constructor
   /// @param source the source information
   /// @param condition the if condition
@@ -41,6 +43,13 @@ class IfStatement : public Statement {
   IfStatement(const Source& source,
               std::unique_ptr<Expression> condition,
               StatementList body);
+  /// Constructor
+  /// @param source the source information
+  /// @param condition the if condition
+  /// @param body the if body
+  IfStatement(const Source& source,
+              std::unique_ptr<Expression> condition,
+              std::unique_ptr<BlockStatement> body);
   /// Move constructor
   IfStatement(IfStatement&&);
   ~IfStatement() override;
@@ -55,9 +64,14 @@ class IfStatement : public Statement {
 
   /// Sets the if body
   /// @param body the if body
-  void set_body(StatementList body) { body_ = std::move(body); }
+  void set_body(StatementList body);
+  /// Sets the if body
+  /// @param body the if body
+  void set_body(std::unique_ptr<BlockStatement> body) {
+    body_ = std::move(body);
+  }
   /// @returns the if body
-  const StatementList& body() const { return body_; }
+  const BlockStatement* body() const { return body_.get(); }
 
   /// Sets the else statements
   /// @param else_statements the else statements to set
@@ -84,7 +98,7 @@ class IfStatement : public Statement {
   IfStatement(const IfStatement&) = delete;
 
   std::unique_ptr<Expression> condition_;
-  StatementList body_;
+  std::unique_ptr<BlockStatement> body_;
   ElseStatementList else_statements_;
 };
 
diff --git a/src/ast/if_statement_test.cc b/src/ast/if_statement_test.cc
index 087ebf7092..bd1e9c9575 100644
--- a/src/ast/if_statement_test.cc
+++ b/src/ast/if_statement_test.cc
@@ -26,22 +26,22 @@ using IfStatementTest = testing::Test;
 
 TEST_F(IfStatementTest, Creation) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   auto* cond_ptr = cond.get();
-  auto* stmt_ptr = body[0].get();
+  auto* stmt_ptr = body->get(0);
 
   IfStatement stmt(std::move(cond), std::move(body));
   EXPECT_EQ(stmt.condition(), cond_ptr);
-  ASSERT_EQ(stmt.body().size(), 1u);
-  EXPECT_EQ(stmt.body()[0].get(), stmt_ptr);
+  ASSERT_EQ(stmt.body()->size(), 1u);
+  EXPECT_EQ(stmt.body()->get(0), stmt_ptr);
 }
 
 TEST_F(IfStatementTest, Creation_WithSource) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   IfStatement stmt(Source{20, 2}, std::move(cond), std::move(body));
   auto src = stmt.source();
@@ -56,8 +56,8 @@ TEST_F(IfStatementTest, IsIf) {
 
 TEST_F(IfStatementTest, IsValid) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   IfStatement stmt(std::move(cond), std::move(body));
   EXPECT_TRUE(stmt.IsValid());
@@ -65,8 +65,8 @@ TEST_F(IfStatementTest, IsValid) {
 
 TEST_F(IfStatementTest, IsValid_WithElseStatements) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   ElseStatementList else_stmts;
   else_stmts.push_back(std::make_unique<ElseStatement>());
@@ -79,8 +79,8 @@ TEST_F(IfStatementTest, IsValid_WithElseStatements) {
 }
 
 TEST_F(IfStatementTest, IsValid_MissingCondition) {
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   IfStatement stmt(nullptr, std::move(body));
   EXPECT_FALSE(stmt.IsValid());
@@ -88,8 +88,8 @@ TEST_F(IfStatementTest, IsValid_MissingCondition) {
 
 TEST_F(IfStatementTest, IsValid_InvalidCondition) {
   auto cond = std::make_unique<IdentifierExpression>("");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   IfStatement stmt(std::move(cond), std::move(body));
   EXPECT_FALSE(stmt.IsValid());
@@ -97,9 +97,9 @@ TEST_F(IfStatementTest, IsValid_InvalidCondition) {
 
 TEST_F(IfStatementTest, IsValid_NullBodyStatement) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
-  body.push_back(nullptr);
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
+  body->append(nullptr);
 
   IfStatement stmt(std::move(cond), std::move(body));
   EXPECT_FALSE(stmt.IsValid());
@@ -107,9 +107,9 @@ TEST_F(IfStatementTest, IsValid_NullBodyStatement) {
 
 TEST_F(IfStatementTest, IsValid_InvalidBodyStatement) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
-  body.push_back(std::make_unique<IfStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
+  body->append(std::make_unique<IfStatement>());
 
   IfStatement stmt(std::move(cond), std::move(body));
   EXPECT_FALSE(stmt.IsValid());
@@ -117,8 +117,8 @@ TEST_F(IfStatementTest, IsValid_InvalidBodyStatement) {
 
 TEST_F(IfStatementTest, IsValid_NullElseStatement) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   ElseStatementList else_stmts;
   else_stmts.push_back(std::make_unique<ElseStatement>());
@@ -133,8 +133,8 @@ TEST_F(IfStatementTest, IsValid_NullElseStatement) {
 
 TEST_F(IfStatementTest, IsValid_InvalidElseStatement) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   ElseStatementList else_stmts;
   else_stmts.push_back(std::make_unique<ElseStatement>());
@@ -147,8 +147,8 @@ TEST_F(IfStatementTest, IsValid_InvalidElseStatement) {
 
 TEST_F(IfStatementTest, IsValid_MultipleElseWiththoutCondition) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   ElseStatementList else_stmts;
   else_stmts.push_back(std::make_unique<ElseStatement>());
@@ -161,8 +161,8 @@ TEST_F(IfStatementTest, IsValid_MultipleElseWiththoutCondition) {
 
 TEST_F(IfStatementTest, IsValid_ElseNotLast) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   ElseStatementList else_stmts;
   else_stmts.push_back(std::make_unique<ElseStatement>());
@@ -176,8 +176,8 @@ TEST_F(IfStatementTest, IsValid_ElseNotLast) {
 
 TEST_F(IfStatementTest, ToStr) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
   IfStatement stmt(std::move(cond), std::move(body));
 
@@ -196,15 +196,15 @@ TEST_F(IfStatementTest, ToStr) {
 
 TEST_F(IfStatementTest, ToStr_WithElseStatements) {
   auto cond = std::make_unique<IdentifierExpression>("cond");
-  StatementList body;
-  body.push_back(std::make_unique<DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<DiscardStatement>());
 
-  StatementList else_if_body;
-  else_if_body.push_back(std::make_unique<DiscardStatement>());
+  auto else_if_body = std::make_unique<BlockStatement>();
+  else_if_body->append(std::make_unique<DiscardStatement>());
 
-  StatementList else_body;
-  else_body.push_back(std::make_unique<DiscardStatement>());
-  else_body.push_back(std::make_unique<DiscardStatement>());
+  auto else_body = std::make_unique<BlockStatement>();
+  else_body->append(std::make_unique<DiscardStatement>());
+  else_body->append(std::make_unique<DiscardStatement>());
 
   ElseStatementList else_stmts;
   else_stmts.push_back(std::make_unique<ElseStatement>());
diff --git a/src/reader/wgsl/parser_impl_else_stmt_test.cc b/src/reader/wgsl/parser_impl_else_stmt_test.cc
index 377f997b33..fa5af49007 100644
--- a/src/reader/wgsl/parser_impl_else_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_else_stmt_test.cc
@@ -29,7 +29,7 @@ TEST_F(ParserImplTest, ElseStmt) {
   ASSERT_NE(e, nullptr);
   ASSERT_TRUE(e->IsElse());
   ASSERT_EQ(e->condition(), nullptr);
-  EXPECT_EQ(e->body().size(), 2u);
+  EXPECT_EQ(e->body()->size(), 2u);
 }
 
 TEST_F(ParserImplTest, ElseStmt_InvalidBody) {
diff --git a/src/reader/wgsl/parser_impl_elseif_stmt_test.cc b/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
index 578006c9bb..13aff03a99 100644
--- a/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
@@ -31,7 +31,7 @@ TEST_F(ParserImplTest, ElseIfStmt) {
   ASSERT_TRUE(e[0]->IsElse());
   ASSERT_NE(e[0]->condition(), nullptr);
   ASSERT_TRUE(e[0]->condition()->IsBinary());
-  EXPECT_EQ(e[0]->body().size(), 2u);
+  EXPECT_EQ(e[0]->body()->size(), 2u);
 }
 
 TEST_F(ParserImplTest, ElseIfStmt_Multiple) {
@@ -43,12 +43,12 @@ TEST_F(ParserImplTest, ElseIfStmt_Multiple) {
   ASSERT_TRUE(e[0]->IsElse());
   ASSERT_NE(e[0]->condition(), nullptr);
   ASSERT_TRUE(e[0]->condition()->IsBinary());
-  EXPECT_EQ(e[0]->body().size(), 2u);
+  EXPECT_EQ(e[0]->body()->size(), 2u);
 
   ASSERT_TRUE(e[1]->IsElse());
   ASSERT_NE(e[1]->condition(), nullptr);
   ASSERT_TRUE(e[1]->condition()->IsIdentifier());
-  EXPECT_EQ(e[1]->body().size(), 1u);
+  EXPECT_EQ(e[1]->body()->size(), 1u);
 }
 
 TEST_F(ParserImplTest, ElseIfStmt_InvalidBody) {
diff --git a/src/reader/wgsl/parser_impl_if_stmt_test.cc b/src/reader/wgsl/parser_impl_if_stmt_test.cc
index 71173adfb2..2898c879d8 100644
--- a/src/reader/wgsl/parser_impl_if_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_if_stmt_test.cc
@@ -32,7 +32,7 @@ TEST_F(ParserImplTest, IfStmt) {
   ASSERT_TRUE(e->IsIf());
   ASSERT_NE(e->condition(), nullptr);
   ASSERT_TRUE(e->condition()->IsBinary());
-  EXPECT_EQ(e->body().size(), 2u);
+  EXPECT_EQ(e->body()->size(), 2u);
   EXPECT_EQ(e->else_statements().size(), 0u);
 }
 
@@ -46,15 +46,15 @@ TEST_F(ParserImplTest, IfStmt_WithElse) {
   ASSERT_TRUE(e->IsIf());
   ASSERT_NE(e->condition(), nullptr);
   ASSERT_TRUE(e->condition()->IsBinary());
-  EXPECT_EQ(e->body().size(), 2u);
+  EXPECT_EQ(e->body()->size(), 2u);
 
   ASSERT_EQ(e->else_statements().size(), 2u);
   ASSERT_NE(e->else_statements()[0]->condition(), nullptr);
   ASSERT_TRUE(e->else_statements()[0]->condition()->IsIdentifier());
-  EXPECT_EQ(e->else_statements()[0]->body().size(), 1u);
+  EXPECT_EQ(e->else_statements()[0]->body()->size(), 1u);
 
   ASSERT_EQ(e->else_statements()[1]->condition(), nullptr);
-  EXPECT_EQ(e->else_statements()[1]->body().size(), 0u);
+  EXPECT_EQ(e->else_statements()[1]->body()->size(), 0u);
 }
 
 TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index a626c90367..7aa5ca8bf8 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -195,9 +195,9 @@ TEST_F(TypeDeterminerTest, Stmt_Else) {
       std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
   auto* rhs_ptr = rhs.get();
 
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::AssignmentStatement>(std::move(lhs),
-                                                            std::move(rhs)));
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::AssignmentStatement>(std::move(lhs),
+                                                          std::move(rhs)));
 
   ast::ElseStatement stmt(std::make_unique<ast::ScalarConstructorExpression>(
                               std::make_unique<ast::SintLiteral>(&i32, 3)),
@@ -224,8 +224,8 @@ TEST_F(TypeDeterminerTest, Stmt_If) {
       std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
   auto* else_rhs_ptr = else_rhs.get();
 
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::AssignmentStatement>(
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::AssignmentStatement>(
       std::move(else_lhs), std::move(else_rhs)));
 
   auto else_stmt = std::make_unique<ast::ElseStatement>(
@@ -244,9 +244,9 @@ TEST_F(TypeDeterminerTest, Stmt_If) {
       std::make_unique<ast::FloatLiteral>(&f32, 2.3f));
   auto* rhs_ptr = rhs.get();
 
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::AssignmentStatement>(std::move(lhs),
-                                                            std::move(rhs)));
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::AssignmentStatement>(std::move(lhs),
+                                                          std::move(rhs)));
 
   ast::IfStatement stmt(std::make_unique<ast::ScalarConstructorExpression>(
                             std::make_unique<ast::SintLiteral>(&i32, 3)),
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index db4af7f355..3a3181cf89 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -1516,12 +1516,12 @@ bool GeneratorImpl::EmitElse(ast::ElseStatement* stmt) {
     if (!EmitExpression(stmt->condition())) {
       return false;
     }
-    out_ << ")";
+    out_ << ") ";
   } else {
-    out_ << " else";
+    out_ << " else ";
   }
 
-  return EmitStatementBlock(stmt->body());
+  return EmitBlock(stmt->body());
 }
 
 bool GeneratorImpl::EmitIf(ast::IfStatement* stmt) {
@@ -1531,9 +1531,9 @@ bool GeneratorImpl::EmitIf(ast::IfStatement* stmt) {
   if (!EmitExpression(stmt->condition())) {
     return false;
   }
-  out_ << ")";
+  out_ << ") ";
 
-  if (!EmitStatementBlock(stmt->body())) {
+  if (!EmitBlock(stmt->body())) {
     return false;
   }
 
@@ -1577,7 +1577,7 @@ bool GeneratorImpl::EmitReturn(ast::ReturnStatement* stmt) {
   return true;
 }
 
-bool GeneratorImpl::EmitBlock(ast::BlockStatement* stmt) {
+bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
   out_ << "{" << std::endl;
   increment_indent();
 
diff --git a/src/writer/msl/generator_impl.h b/src/writer/msl/generator_impl.h
index 4178a30e7a..92d0c0bf29 100644
--- a/src/writer/msl/generator_impl.h
+++ b/src/writer/msl/generator_impl.h
@@ -76,7 +76,7 @@ class GeneratorImpl : public TextGenerator {
   /// Handles a block statement
   /// @param stmt the statement to emit
   /// @returns true if the statement was emitted successfully
-  bool EmitBlock(ast::BlockStatement* stmt);
+  bool EmitBlock(const ast::BlockStatement* stmt);
   /// Handles a block statement with a newline at the end
   /// @param stmt the statement to emit
   /// @returns true if the statement was emitted successfully
diff --git a/src/writer/msl/generator_impl_function_test.cc b/src/writer/msl/generator_impl_function_test.cc
index 4a810e65e7..c8ea76481d 100644
--- a/src/writer/msl/generator_impl_function_test.cc
+++ b/src/writer/msl/generator_impl_function_test.cc
@@ -971,8 +971,9 @@ TEST_F(MslGeneratorImplTest,
       std::make_unique<ast::ScalarConstructorExpression>(
           std::make_unique<ast::FloatLiteral>(&f32, 1.0f))));
 
-  ast::StatementList list;
-  list.push_back(std::make_unique<ast::ReturnStatement>());
+  auto list = std::make_unique<ast::BlockStatement>();
+  list->append(std::make_unique<ast::ReturnStatement>());
+
   body->append(std::make_unique<ast::IfStatement>(
       std::make_unique<ast::BinaryExpression>(
           ast::BinaryOp::kEqual,
diff --git a/src/writer/msl/generator_impl_if_test.cc b/src/writer/msl/generator_impl_if_test.cc
index e2c275541e..8686b14918 100644
--- a/src/writer/msl/generator_impl_if_test.cc
+++ b/src/writer/msl/generator_impl_if_test.cc
@@ -29,8 +29,8 @@ using MslGeneratorImplTest = testing::Test;
 
 TEST_F(MslGeneratorImplTest, Emit_If) {
   auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::ReturnStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::ReturnStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
 
@@ -47,17 +47,16 @@ TEST_F(MslGeneratorImplTest, Emit_If) {
 
 TEST_F(MslGeneratorImplTest, Emit_IfWithElseIf) {
   auto else_cond = std::make_unique<ast::IdentifierExpression>("else_cond");
-
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::ReturnStatement>());
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::ReturnStatement>());
 
   ast::ElseStatementList elses;
   elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_cond),
                                                        std::move(else_body)));
 
   auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::ReturnStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::ReturnStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
@@ -76,15 +75,15 @@ TEST_F(MslGeneratorImplTest, Emit_IfWithElseIf) {
 }
 
 TEST_F(MslGeneratorImplTest, Emit_IfWithElse) {
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::ReturnStatement>());
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::ReturnStatement>());
 
   ast::ElseStatementList elses;
   elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_body)));
 
   auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::ReturnStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::ReturnStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
@@ -105,11 +104,11 @@ TEST_F(MslGeneratorImplTest, Emit_IfWithElse) {
 TEST_F(MslGeneratorImplTest, Emit_IfWithMultiple) {
   auto else_cond = std::make_unique<ast::IdentifierExpression>("else_cond");
 
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::ReturnStatement>());
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::ReturnStatement>());
 
-  ast::StatementList else_body_2;
-  else_body_2.push_back(std::make_unique<ast::ReturnStatement>());
+  auto else_body_2 = std::make_unique<ast::BlockStatement>();
+  else_body_2->append(std::make_unique<ast::ReturnStatement>());
 
   ast::ElseStatementList elses;
   elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_cond),
@@ -117,8 +116,8 @@ TEST_F(MslGeneratorImplTest, Emit_IfWithMultiple) {
   elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_body_2)));
 
   auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::ReturnStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::ReturnStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 5fd41f8899..a214684e0c 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -1600,7 +1600,7 @@ uint32_t Builder::GenerateCastExpression(ast::CastExpression* cast) {
 
 bool Builder::GenerateConditionalBlock(
     ast::Expression* cond,
-    const ast::StatementList& true_body,
+    const ast::BlockStatement* true_body,
     size_t cur_else_idx,
     const ast::ElseStatementList& else_stmts) {
   auto cond_id = GenerateExpression(cond);
@@ -1629,7 +1629,7 @@ bool Builder::GenerateConditionalBlock(
 
   // Output true block
   GenerateLabel(true_block_id);
-  if (!GenerateStatementList(true_body)) {
+  if (!GenerateBlockStatement(true_body)) {
     return false;
   }
   // We only branch if the last element of the body didn't already branch.
@@ -1644,7 +1644,7 @@ bool Builder::GenerateConditionalBlock(
     auto* else_stmt = else_stmts[cur_else_idx].get();
     // Handle the else case by just outputting the statements.
     if (!else_stmt->HasCondition()) {
-      if (!GenerateStatementList(else_stmt->body())) {
+      if (!GenerateBlockStatement(else_stmt->body())) {
         return false;
       }
     } else {
diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h
index e78755655e..2e1a82b03c 100644
--- a/src/writer/spirv/builder.h
+++ b/src/writer/spirv/builder.h
@@ -308,7 +308,7 @@ class Builder {
   /// @param else_stmts the list of all else statements
   /// @returns true on success, false on failure
   bool GenerateConditionalBlock(ast::Expression* cond,
-                                const ast::StatementList& true_body,
+                                const ast::BlockStatement* true_body,
                                 size_t cur_else_idx,
                                 const ast::ElseStatementList& else_stmts);
   /// Generates a statement
diff --git a/src/writer/spirv/builder_if_test.cc b/src/writer/spirv/builder_if_test.cc
index ceaff32a22..213be80539 100644
--- a/src/writer/spirv/builder_if_test.cc
+++ b/src/writer/spirv/builder_if_test.cc
@@ -48,7 +48,8 @@ TEST_F(BuilderTest, If_Empty) {
   auto cond = std::make_unique<ast::ScalarConstructorExpression>(
       std::make_unique<ast::BoolLiteral>(&bool_type, true));
 
-  ast::IfStatement expr(std::move(cond), ast::StatementList{});
+  ast::IfStatement expr(std::move(cond),
+                        std::make_unique<ast::BlockStatement>());
 
   Context ctx;
   ast::Module mod;
@@ -81,8 +82,8 @@ TEST_F(BuilderTest, If_WithStatements) {
   auto var =
       std::make_unique<ast::Variable>("v", ast::StorageClass::kPrivate, &i32);
 
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::AssignmentStatement>(
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::AssignmentStatement>(
       std::make_unique<ast::IdentifierExpression>("v"),
       std::make_unique<ast::ScalarConstructorExpression>(
           std::make_unique<ast::SintLiteral>(&i32, 2))));
@@ -133,14 +134,14 @@ TEST_F(BuilderTest, If_WithElse) {
   auto var =
       std::make_unique<ast::Variable>("v", ast::StorageClass::kPrivate, &i32);
 
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::AssignmentStatement>(
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::AssignmentStatement>(
       std::make_unique<ast::IdentifierExpression>("v"),
       std::make_unique<ast::ScalarConstructorExpression>(
           std::make_unique<ast::SintLiteral>(&i32, 2))));
 
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::AssignmentStatement>(
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::AssignmentStatement>(
       std::make_unique<ast::IdentifierExpression>("v"),
       std::make_unique<ast::ScalarConstructorExpression>(
           std::make_unique<ast::SintLiteral>(&i32, 3))));
@@ -201,14 +202,14 @@ TEST_F(BuilderTest, If_WithElseIf) {
   auto var =
       std::make_unique<ast::Variable>("v", ast::StorageClass::kPrivate, &i32);
 
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::AssignmentStatement>(
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::AssignmentStatement>(
       std::make_unique<ast::IdentifierExpression>("v"),
       std::make_unique<ast::ScalarConstructorExpression>(
           std::make_unique<ast::SintLiteral>(&i32, 2))));
 
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::AssignmentStatement>(
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::AssignmentStatement>(
       std::make_unique<ast::IdentifierExpression>("v"),
       std::make_unique<ast::ScalarConstructorExpression>(
           std::make_unique<ast::SintLiteral>(&i32, 3))));
@@ -281,23 +282,23 @@ TEST_F(BuilderTest, If_WithMultiple) {
   auto var =
       std::make_unique<ast::Variable>("v", ast::StorageClass::kPrivate, &i32);
 
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::AssignmentStatement>(
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::AssignmentStatement>(
       std::make_unique<ast::IdentifierExpression>("v"),
       std::make_unique<ast::ScalarConstructorExpression>(
           std::make_unique<ast::SintLiteral>(&i32, 2))));
-  ast::StatementList elseif_1_body;
-  elseif_1_body.push_back(std::make_unique<ast::AssignmentStatement>(
+  auto elseif_1_body = std::make_unique<ast::BlockStatement>();
+  elseif_1_body->append(std::make_unique<ast::AssignmentStatement>(
       std::make_unique<ast::IdentifierExpression>("v"),
       std::make_unique<ast::ScalarConstructorExpression>(
           std::make_unique<ast::SintLiteral>(&i32, 3))));
-  ast::StatementList elseif_2_body;
-  elseif_2_body.push_back(std::make_unique<ast::AssignmentStatement>(
+  auto elseif_2_body = std::make_unique<ast::BlockStatement>();
+  elseif_2_body->append(std::make_unique<ast::AssignmentStatement>(
       std::make_unique<ast::IdentifierExpression>("v"),
       std::make_unique<ast::ScalarConstructorExpression>(
           std::make_unique<ast::SintLiteral>(&i32, 4))));
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::AssignmentStatement>(
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::AssignmentStatement>(
       std::make_unique<ast::IdentifierExpression>("v"),
       std::make_unique<ast::ScalarConstructorExpression>(
           std::make_unique<ast::SintLiteral>(&i32, 5))));
@@ -384,8 +385,8 @@ TEST_F(BuilderTest, If_WithBreak) {
   auto cond = std::make_unique<ast::ScalarConstructorExpression>(
       std::make_unique<ast::BoolLiteral>(&bool_type, true));
 
-  ast::StatementList if_body;
-  if_body.push_back(std::make_unique<ast::BreakStatement>());
+  auto if_body = std::make_unique<ast::BlockStatement>();
+  if_body->append(std::make_unique<ast::BreakStatement>());
 
   auto if_stmt =
       std::make_unique<ast::IfStatement>(std::move(cond), std::move(if_body));
@@ -437,16 +438,15 @@ TEST_F(BuilderTest, If_WithElseBreak) {
   auto cond = std::make_unique<ast::ScalarConstructorExpression>(
       std::make_unique<ast::BoolLiteral>(&bool_type, true));
 
-  ast::StatementList if_body;
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::BreakStatement>());
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::BreakStatement>());
 
   ast::ElseStatementList else_stmts;
   else_stmts.push_back(
       std::make_unique<ast::ElseStatement>(std::move(else_body)));
 
-  auto if_stmt =
-      std::make_unique<ast::IfStatement>(std::move(cond), std::move(if_body));
+  auto if_stmt = std::make_unique<ast::IfStatement>(
+      std::move(cond), std::make_unique<ast::BlockStatement>());
   if_stmt->set_else_statements(std::move(else_stmts));
 
   ast::StatementList loop_body;
@@ -497,8 +497,8 @@ TEST_F(BuilderTest, If_WithContinue) {
   auto cond = std::make_unique<ast::ScalarConstructorExpression>(
       std::make_unique<ast::BoolLiteral>(&bool_type, true));
 
-  ast::StatementList if_body;
-  if_body.push_back(std::make_unique<ast::ContinueStatement>());
+  auto if_body = std::make_unique<ast::BlockStatement>();
+  if_body->append(std::make_unique<ast::ContinueStatement>());
 
   auto if_stmt =
       std::make_unique<ast::IfStatement>(std::move(cond), std::move(if_body));
@@ -550,16 +550,15 @@ TEST_F(BuilderTest, If_WithElseContinue) {
   auto cond = std::make_unique<ast::ScalarConstructorExpression>(
       std::make_unique<ast::BoolLiteral>(&bool_type, true));
 
-  ast::StatementList if_body;
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::ContinueStatement>());
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::ContinueStatement>());
 
   ast::ElseStatementList else_stmts;
   else_stmts.push_back(
       std::make_unique<ast::ElseStatement>(std::move(else_body)));
 
-  auto if_stmt =
-      std::make_unique<ast::IfStatement>(std::move(cond), std::move(if_body));
+  auto if_stmt = std::make_unique<ast::IfStatement>(
+      std::move(cond), std::make_unique<ast::BlockStatement>());
   if_stmt->set_else_statements(std::move(else_stmts));
 
   ast::StatementList loop_body;
@@ -608,8 +607,8 @@ TEST_F(BuilderTest, If_WithReturn) {
   auto cond = std::make_unique<ast::ScalarConstructorExpression>(
       std::make_unique<ast::BoolLiteral>(&bool_type, true));
 
-  ast::StatementList if_body;
-  if_body.push_back(std::make_unique<ast::ReturnStatement>());
+  auto if_body = std::make_unique<ast::BlockStatement>();
+  if_body->append(std::make_unique<ast::ReturnStatement>());
 
   ast::IfStatement expr(std::move(cond), std::move(if_body));
 
@@ -645,8 +644,8 @@ TEST_F(BuilderTest, If_WithReturnValue) {
   auto cond2 = std::make_unique<ast::ScalarConstructorExpression>(
       std::make_unique<ast::BoolLiteral>(&bool_type, false));
 
-  ast::StatementList if_body;
-  if_body.push_back(std::make_unique<ast::ReturnStatement>(std::move(cond2)));
+  auto if_body = std::make_unique<ast::BlockStatement>();
+  if_body->append(std::make_unique<ast::ReturnStatement>(std::move(cond2)));
 
   ast::IfStatement expr(std::move(cond), std::move(if_body));
 
diff --git a/src/writer/spirv/builder_switch_test.cc b/src/writer/spirv/builder_switch_test.cc
index 4cd7c538f9..28a0b36065 100644
--- a/src/writer/spirv/builder_switch_test.cc
+++ b/src/writer/spirv/builder_switch_test.cc
@@ -489,8 +489,8 @@ TEST_F(BuilderTest, Switch_WithNestedBreak) {
   auto a =
       std::make_unique<ast::Variable>("a", ast::StorageClass::kPrivate, &i32);
 
-  ast::StatementList if_body;
-  if_body.push_back(std::make_unique<ast::BreakStatement>());
+  auto if_body = std::make_unique<ast::BlockStatement>();
+  if_body->append(std::make_unique<ast::BreakStatement>());
 
   auto case_1_body = std::make_unique<ast::BlockStatement>();
   case_1_body->append(std::make_unique<ast::IfStatement>(
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index ac8ba767e7..6da382f5bc 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -771,12 +771,12 @@ bool GeneratorImpl::EmitElse(ast::ElseStatement* stmt) {
     if (!EmitExpression(stmt->condition())) {
       return false;
     }
-    out_ << ")";
+    out_ << ") ";
   } else {
-    out_ << " else";
+    out_ << " else ";
   }
 
-  return EmitStatementBlock(stmt->body());
+  return EmitBlock(stmt->body());
 }
 
 bool GeneratorImpl::EmitFallthrough(ast::FallthroughStatement*) {
@@ -792,9 +792,9 @@ bool GeneratorImpl::EmitIf(ast::IfStatement* stmt) {
   if (!EmitExpression(stmt->condition())) {
     return false;
   }
-  out_ << ")";
+  out_ << ") ";
 
-  if (!EmitStatementBlock(stmt->body())) {
+  if (!EmitBlock(stmt->body())) {
     return false;
   }
 
diff --git a/src/writer/wgsl/generator_impl_if_test.cc b/src/writer/wgsl/generator_impl_if_test.cc
index 2c8e340086..985f6da7a9 100644
--- a/src/writer/wgsl/generator_impl_if_test.cc
+++ b/src/writer/wgsl/generator_impl_if_test.cc
@@ -28,8 +28,8 @@ using WgslGeneratorImplTest = testing::Test;
 
 TEST_F(WgslGeneratorImplTest, Emit_If) {
   auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::DiscardStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
 
@@ -45,17 +45,16 @@ TEST_F(WgslGeneratorImplTest, Emit_If) {
 
 TEST_F(WgslGeneratorImplTest, Emit_IfWithElseIf) {
   auto else_cond = std::make_unique<ast::IdentifierExpression>("else_cond");
-
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::DiscardStatement>());
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::DiscardStatement>());
 
   ast::ElseStatementList elses;
   elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_cond),
                                                        std::move(else_body)));
 
   auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::DiscardStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
@@ -73,15 +72,15 @@ TEST_F(WgslGeneratorImplTest, Emit_IfWithElseIf) {
 }
 
 TEST_F(WgslGeneratorImplTest, Emit_IfWithElse) {
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::DiscardStatement>());
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::DiscardStatement>());
 
   ast::ElseStatementList elses;
   elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_body)));
 
   auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::DiscardStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
@@ -101,11 +100,11 @@ TEST_F(WgslGeneratorImplTest, Emit_IfWithElse) {
 TEST_F(WgslGeneratorImplTest, Emit_IfWithMultiple) {
   auto else_cond = std::make_unique<ast::IdentifierExpression>("else_cond");
 
-  ast::StatementList else_body;
-  else_body.push_back(std::make_unique<ast::DiscardStatement>());
+  auto else_body = std::make_unique<ast::BlockStatement>();
+  else_body->append(std::make_unique<ast::DiscardStatement>());
 
-  ast::StatementList else_body_2;
-  else_body_2.push_back(std::make_unique<ast::DiscardStatement>());
+  auto else_body_2 = std::make_unique<ast::BlockStatement>();
+  else_body_2->append(std::make_unique<ast::DiscardStatement>());
 
   ast::ElseStatementList elses;
   elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_cond),
@@ -113,8 +112,8 @@ TEST_F(WgslGeneratorImplTest, Emit_IfWithMultiple) {
   elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_body_2)));
 
   auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  ast::StatementList body;
-  body.push_back(std::make_unique<ast::DiscardStatement>());
+  auto body = std::make_unique<ast::BlockStatement>();
+  body->append(std::make_unique<ast::DiscardStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));