// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "fidl/flat_ast.h"

#include <assert.h>
#include <stdio.h>

#include <algorithm>
#include <iostream>
#include <sstream>
#include <utility>

#include "fidl/attributes.h"
#include "fidl/diagnostic_types.h"
#include "fidl/diagnostics.h"
#include "fidl/experimental_flags.h"
#include "fidl/lexer.h"
#include "fidl/names.h"
#include "fidl/ordinals.h"
#include "fidl/parser.h"
#include "fidl/raw_ast.h"
#include "fidl/types.h"
#include "fidl/utils.h"

namespace fidl {
namespace flat {

using namespace diagnostics;

namespace {

constexpr uint32_t kHandleSameRights = 0x80000000;  // ZX_HANDLE_SAME_RIGHTS

class ScopeInsertResult {
 public:
  explicit ScopeInsertResult(std::unique_ptr<SourceSpan> previous_occurrence)
      : previous_occurrence_(std::move(previous_occurrence)) {}

  static ScopeInsertResult Ok() { return ScopeInsertResult(nullptr); }
  static ScopeInsertResult FailureAt(SourceSpan previous) {
    return ScopeInsertResult(std::make_unique<SourceSpan>(previous));
  }

  bool ok() const { return previous_occurrence_ == nullptr; }

  const SourceSpan& previous_occurrence() const {
    assert(!ok());
    return *previous_occurrence_;
  }

 private:
  std::unique_ptr<SourceSpan> previous_occurrence_;
};

template <typename T>
class Scope {
 public:
  ScopeInsertResult Insert(const T& t, SourceSpan span) {
    auto iter = scope_.find(t);
    if (iter != scope_.end()) {
      return ScopeInsertResult::FailureAt(iter->second);
    } else {
      scope_.emplace(t, span);
      return ScopeInsertResult::Ok();
    }
  }

  typename std::map<T, SourceSpan>::const_iterator begin() const { return scope_.begin(); }

  typename std::map<T, SourceSpan>::const_iterator end() const { return scope_.end(); }

 private:
  std::map<T, SourceSpan> scope_;
};

using Ordinal64Scope = Scope<uint64_t>;

std::optional<std::pair<uint64_t, SourceSpan>> FindFirstNonDenseOrdinal(
    const Ordinal64Scope& scope) {
  uint64_t last_ordinal_seen = 0;
  for (const auto& ordinal_and_loc : scope) {
    uint64_t next_expected_ordinal = last_ordinal_seen + 1;
    if (ordinal_and_loc.first != next_expected_ordinal) {
      return std::optional{std::make_pair(next_expected_ordinal, ordinal_and_loc.second)};
    }
    last_ordinal_seen = ordinal_and_loc.first;
  }
  return std::nullopt;
}

struct MethodScope {
  Ordinal64Scope ordinals;
  Scope<std::string> canonical_names;
  Scope<const Protocol*> protocols;
};

// A helper class to derive the resourceness of synthesized decls based on their
// members. If the given std::optional<types::Resourceness> is already set
// (meaning the decl is user-defined, not synthesized), this does nothing.
//
// Types added via AddType must already be compiled. In other words, there must
// not be cycles among the synthesized decls.
class DeriveResourceness {
 public:
  explicit DeriveResourceness(std::optional<types::Resourceness>* target)
      : target_(target), derive_(!target->has_value()), result_(types::Resourceness::kValue) {}

  ~DeriveResourceness() {
    if (derive_) {
      *target_ = result_;
    }
  }

  void AddType(const Type* type) {
    if (derive_ && result_ == types::Resourceness::kValue &&
        type->Resourceness() == types::Resourceness::kResource) {
      result_ = types::Resourceness::kResource;
    }
  }

 private:
  std::optional<types::Resourceness>* const target_;
  const bool derive_;
  types::Resourceness result_;
};

// A helper class to track when a Decl is compiling and compiled.
class Compiling {
 public:
  explicit Compiling(Decl* decl) : decl_(decl) { decl_->compiling = true; }

  ~Compiling() {
    decl_->compiling = false;
    decl_->compiled = true;
  }

 private:
  Decl* decl_;
};

template <typename T>
std::unique_ptr<Diagnostic> ValidateUnknownConstraints(const Decl& decl,
                                                       types::Strictness decl_strictness,
                                                       const std::vector<const T*>* members) {
  if (!members)
    return nullptr;

  const bool is_transitional = decl.HasAttribute("Transitional");

  const bool is_strict = [&] {
    switch (decl_strictness) {
      case types::Strictness::kStrict:
        return true;
      case types::Strictness::kFlexible:
        return false;
    }
  }();

  bool found_member = false;
  for (const auto* member : *members) {
    const bool has_unknown = member->attributes && member->attributes->HasAttribute("Unknown");
    if (!has_unknown)
      continue;

    if (is_strict && !is_transitional) {
      return Reporter::MakeError(ErrUnknownAttributeOnInvalidType, member->name);
    }

    if (found_member) {
      return Reporter::MakeError(ErrUnknownAttributeOnMultipleMembers, member->name);
    }

    found_member = true;
  }

  return nullptr;
}

}  // namespace

uint32_t PrimitiveType::SubtypeSize(types::PrimitiveSubtype subtype) {
  switch (subtype) {
    case types::PrimitiveSubtype::kBool:
    case types::PrimitiveSubtype::kInt8:
    case types::PrimitiveSubtype::kUint8:
      return 1u;

    case types::PrimitiveSubtype::kInt16:
    case types::PrimitiveSubtype::kUint16:
      return 2u;

    case types::PrimitiveSubtype::kFloat32:
    case types::PrimitiveSubtype::kInt32:
    case types::PrimitiveSubtype::kUint32:
      return 4u;

    case types::PrimitiveSubtype::kFloat64:
    case types::PrimitiveSubtype::kInt64:
    case types::PrimitiveSubtype::kUint64:
      return 8u;
  }
}

bool Decl::HasAttribute(std::string_view name) const {
  if (!attributes)
    return false;
  return attributes->HasAttribute(std::string(name));
}

std::string_view Decl::GetAttribute(std::string_view name) const {
  if (!attributes)
    return std::string_view();
  for (const auto& attribute : attributes->attributes) {
    if (attribute.name == name) {
      if (attribute.value != "") {
        const auto& value = attribute.value;
        return std::string_view(value.data(), value.size());
      }
      // Don't search for another attribute with the same name.
      break;
    }
  }
  return std::string_view();
}

std::string Decl::GetName() const { return std::string(name.decl_name()); }

const std::set<std::pair<std::string, std::string_view>> allowed_simple_unions{{
    {"fuchsia.io", "NodeInfo"},
}};

bool IsSimple(const Type* type, Reporter* reporter) {
  auto depth = fidl::OldWireFormatDepth(type);
  switch (type->kind) {
    case Type::Kind::kVector: {
      auto vector_type = static_cast<const VectorType*>(type);
      if (*vector_type->element_count == Size::Max())
        return false;
      switch (vector_type->element_type->kind) {
        case Type::Kind::kHandle:
        case Type::Kind::kRequestHandle:
        case Type::Kind::kPrimitive:
          return true;
        case Type::Kind::kArray:
        case Type::Kind::kVector:
        case Type::Kind::kString:
        case Type::Kind::kIdentifier:
          return false;
      }
    }
    case Type::Kind::kString: {
      auto string_type = static_cast<const StringType*>(type);
      return *string_type->max_size < Size::Max();
    }
    case Type::Kind::kArray:
    case Type::Kind::kHandle:
    case Type::Kind::kRequestHandle:
    case Type::Kind::kPrimitive:
      return depth == 0u;
    case Type::Kind::kIdentifier: {
      auto identifier_type = static_cast<const IdentifierType*>(type);
      if (identifier_type->type_decl->kind == Decl::Kind::kUnion) {
        auto union_name = std::make_pair<const std::string&, const std::string_view&>(
            LibraryName(identifier_type->name.library(), "."), identifier_type->name.decl_name());
        if (allowed_simple_unions.find(union_name) == allowed_simple_unions.end()) {
          // Any unions not in the allow-list are treated as non-simple.
          reporter->Report(ErrUnionCannotBeSimple, identifier_type->name.span(),
                           identifier_type->name);
          return false;
        }
      }
      switch (identifier_type->nullability) {
        case types::Nullability::kNullable:
          // If the identifier is nullable, then we can handle a depth of 1
          // because the secondary object is directly accessible.
          return depth <= 1u;
        case types::Nullability::kNonnullable:
          return depth == 0u;
      }
    }
  }
}

FieldShape Struct::Member::fieldshape(WireFormat wire_format) const {
  return FieldShape(*this, wire_format);
}

FieldShape Table::Member::Used::fieldshape(WireFormat wire_format) const {
  return FieldShape(*this, wire_format);
}

FieldShape Union::Member::Used::fieldshape(WireFormat wire_format) const {
  return FieldShape(*this, wire_format);
}

std::vector<std::reference_wrapper<const Union::Member>> Union::MembersSortedByXUnionOrdinal()
    const {
  std::vector<std::reference_wrapper<const Member>> sorted_members(members.cbegin(),
                                                                   members.cend());
  std::sort(sorted_members.begin(), sorted_members.end(),
            [](const auto& member1, const auto& member2) {
              return member1.get().ordinal->value < member2.get().ordinal->value;
            });
  return sorted_members;
}

bool Typespace::Create(const flat::Name& name, const Type* arg_type,
                       const std::optional<uint32_t>& obj_type,
                       const std::optional<types::HandleSubtype>& handle_subtype,
                       const Constant* handle_rights, const Size* size,
                       types::Nullability nullability, const Type** out_type,
                       std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) {
  std::unique_ptr<Type> type;
  if (!CreateNotOwned(name, arg_type, obj_type, handle_subtype, handle_rights, size, nullability,
                      &type, out_from_type_alias))
    return false;
  types_.push_back(std::move(type));
  *out_type = types_.back().get();
  return true;
}

bool Typespace::CreateNotOwned(const flat::Name& name, const Type* arg_type,
                               const std::optional<uint32_t>& obj_type,
                               const std::optional<types::HandleSubtype>& handle_subtype,
                               const Constant* handle_rights, const Size* size,
                               types::Nullability nullability, std::unique_ptr<Type>* out_type,
                               std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) {
  // TODO(pascallouis): lookup whether we've already created the type, and
  // return it rather than create a new one. Lookup must be by name,
  // arg_type, size, and nullability.

  auto type_template = LookupTemplate(name);
  if (type_template == nullptr) {
    reporter_->Report(ErrUnknownType, name.span(), name);
    return false;
  }
  return type_template->Create({.span = name.span(),
                                .arg_type = arg_type,
                                .obj_type = obj_type,
                                .handle_subtype = handle_subtype,
                                .handle_rights = handle_rights,
                                .size = size,
                                .nullability = nullability},
                               out_type, out_from_type_alias);
}

void Typespace::AddTemplate(std::unique_ptr<TypeTemplate> type_template) {
  templates_.emplace(type_template->name(), std::move(type_template));
}

const TypeTemplate* Typespace::LookupTemplate(const flat::Name& name) const {
  auto global_name = Name::Key(nullptr, name.decl_name());
  if (auto iter = templates_.find(global_name); iter != templates_.end()) {
    return iter->second.get();
  }

  if (auto iter = templates_.find(name); iter != templates_.end()) {
    return iter->second.get();
  }

  return nullptr;
}

bool TypeTemplate::Fail(const ErrorDef<const TypeTemplate*>& err,
                        const std::optional<SourceSpan>& span) const {
  reporter_->Report(err, span, this);
  return false;
}

class PrimitiveTypeTemplate : public TypeTemplate {
 public:
  PrimitiveTypeTemplate(Typespace* typespace, Reporter* reporter, const std::string& name,
                        types::PrimitiveSubtype subtype)
      : TypeTemplate(Name::CreateIntrinsic(name), typespace, reporter), subtype_(subtype) {}

  bool Create(const CreateInvocation& args, std::unique_ptr<Type>* out_type,
              std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) const {
    assert(!args.handle_subtype);
    assert(!args.handle_rights);

    if (args.arg_type != nullptr)
      return Fail(ErrCannotBeParameterized, args.span);
    if (args.size != nullptr)
      return Fail(ErrCannotHaveSize, args.span);
    if (args.nullability == types::Nullability::kNullable)
      return Fail(ErrCannotBeNullable, args.span);

    *out_type = std::make_unique<PrimitiveType>(name_, subtype_);
    return true;
  }

 private:
  const types::PrimitiveSubtype subtype_;
};

class BytesTypeTemplate final : public TypeTemplate {
 public:
  BytesTypeTemplate(Typespace* typespace, Reporter* reporter)
      : TypeTemplate(Name::CreateIntrinsic("vector"), typespace, reporter),
        uint8_type_(kUint8Type) {}

  bool Create(const CreateInvocation& args, std::unique_ptr<Type>* out_type,
              std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) const {
    assert(!args.handle_subtype);
    assert(!args.handle_rights);

    if (args.arg_type != nullptr)
      return Fail(ErrCannotBeParameterized, args.span);
    const Size* size = args.size;
    if (size == nullptr)
      size = &max_size;

    *out_type = std::make_unique<VectorType>(name_, &uint8_type_, size, args.nullability);
    return true;
  }

 private:
  // TODO(fxbug.dev/7724): Remove when canonicalizing types.
  const Name kUint8TypeName = Name::CreateIntrinsic("uint8");
  const PrimitiveType kUint8Type = PrimitiveType(kUint8TypeName, types::PrimitiveSubtype::kUint8);

  const PrimitiveType uint8_type_;
  Size max_size = Size::Max();
};

class ArrayTypeTemplate final : public TypeTemplate {
 public:
  ArrayTypeTemplate(Typespace* typespace, Reporter* reporter)
      : TypeTemplate(Name::CreateIntrinsic("array"), typespace, reporter) {}

  bool Create(const CreateInvocation& args, std::unique_ptr<Type>* out_type,
              std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) const {
    assert(!args.handle_subtype);
    assert(!args.handle_rights);

    if (args.arg_type == nullptr)
      return Fail(ErrMustBeParameterized, args.span);
    if (args.size == nullptr)
      return Fail(ErrMustHaveSize, args.span);
    if (args.size->value == 0)
      return Fail(ErrMustHaveNonZeroSize, args.span);
    if (args.nullability == types::Nullability::kNullable)
      return Fail(ErrCannotBeNullable, args.span);

    *out_type = std::make_unique<ArrayType>(name_, args.arg_type, args.size);
    return true;
  }
};

class VectorTypeTemplate final : public TypeTemplate {
 public:
  VectorTypeTemplate(Typespace* typespace, Reporter* reporter)
      : TypeTemplate(Name::CreateIntrinsic("vector"), typespace, reporter) {}

  bool Create(const CreateInvocation& args, std::unique_ptr<Type>* out_type,
              std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) const {
    assert(!args.handle_subtype);
    assert(!args.handle_rights);

    if (args.arg_type == nullptr)
      return Fail(ErrMustBeParameterized, args.span);
    const Size* size = args.size;
    if (size == nullptr)
      size = &max_size;

    *out_type = std::make_unique<VectorType>(name_, args.arg_type, size, args.nullability);
    return true;
  }

 private:
  Size max_size = Size::Max();
};

class StringTypeTemplate final : public TypeTemplate {
 public:
  StringTypeTemplate(Typespace* typespace, Reporter* reporter)
      : TypeTemplate(Name::CreateIntrinsic("string"), typespace, reporter) {}

  bool Create(const CreateInvocation& args, std::unique_ptr<Type>* out_type,
              std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) const {
    assert(!args.handle_subtype);
    assert(!args.handle_rights);

    if (args.arg_type != nullptr)
      return Fail(ErrCannotBeParameterized, args.span);
    const Size* size = args.size;
    if (size == nullptr)
      size = &max_size;

    *out_type = std::make_unique<StringType>(name_, size, args.nullability);
    return true;
  }

 private:
  Size max_size = Size::Max();
};

class HandleTypeTemplate final : public TypeTemplate {
 public:
  HandleTypeTemplate(Typespace* typespace, Reporter* reporter)
      : TypeTemplate(Name::CreateIntrinsic("handle"), typespace, reporter) {
    same_rights = std::make_unique<Constant>(Constant::Kind::kSynthesized, SourceSpan());
    same_rights->ResolveTo(std::make_unique<NumericConstantValue<uint32_t>>(kHandleSameRights));
  }

  bool Create(const CreateInvocation& args, std::unique_ptr<Type>* out_type,
              std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) const {
    assert(args.arg_type == nullptr);

    if (args.size != nullptr)
      return Fail(ErrCannotHaveSize, args.span);

    // TODO(fxbug.dev/64629): When we are ready to create handle types, we
    // should have an object type (and/or subtype) determined and not require
    // these hardcoded defaults.
    auto obj_type = args.obj_type.value_or(static_cast<uint32_t>(types::HandleSubtype::kHandle));
    auto handle_subtype = args.handle_subtype.value_or(types::HandleSubtype::kHandle);
    const Constant* handle_rights = args.handle_rights;
    if (handle_rights == nullptr)
      handle_rights = same_rights.get();

    *out_type = std::make_unique<HandleType>(name_, obj_type, handle_subtype, handle_rights,
                                             args.nullability);
    return true;
  }

 private:
  std::unique_ptr<Constant> same_rights;
};

class RequestTypeTemplate final : public TypeTemplate {
 public:
  RequestTypeTemplate(Typespace* typespace, Reporter* reporter)
      : TypeTemplate(Name::CreateIntrinsic("request"), typespace, reporter) {}

  bool Create(const CreateInvocation& args, std::unique_ptr<Type>* out_type,
              std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) const {
    assert(!args.handle_subtype);
    assert(!args.handle_rights);

    if (args.arg_type == nullptr)
      return Fail(ErrMustBeParameterized, args.span);
    if (args.arg_type->kind != Type::Kind::kIdentifier)
      return Fail(ErrMustBeAProtocol, args.span);
    auto protocol_type = static_cast<const IdentifierType*>(args.arg_type);
    if (protocol_type->type_decl->kind != Decl::Kind::kProtocol)
      return Fail(ErrMustBeAProtocol, args.span);
    if (args.size != nullptr)
      return Fail(ErrCannotHaveSize, args.span);

    *out_type = std::make_unique<RequestHandleType>(name_, protocol_type, args.nullability);
    return true;
  }

 private:
  // TODO(pascallouis): Make Min/Max an actual value on NumericConstantValue
  // class, to simply write &Size::Max() above.
  Size max_size = Size::Max();
};

class TypeDeclTypeTemplate final : public TypeTemplate {
 public:
  TypeDeclTypeTemplate(Name name, Typespace* typespace, Reporter* reporter, Library* library,
                       TypeDecl* type_decl)
      : TypeTemplate(std::move(name), typespace, reporter),
        library_(library),
        type_decl_(type_decl) {}

  bool Create(const CreateInvocation& args, std::unique_ptr<Type>* out_type,
              std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) const {
    assert(!args.handle_subtype);

    if (!type_decl_->compiled && type_decl_->kind != Decl::Kind::kProtocol) {
      if (type_decl_->compiling) {
        type_decl_->recursive = true;
      } else {
        if (!library_->CompileDecl(type_decl_)) {
          return false;
        }
      }
    }
    switch (type_decl_->kind) {
      case Decl::Kind::kService:
      case Decl::Kind::kProtocol:
        break;

      case Decl::Kind::kUnion:
        // Do nothing here: nullable Unions have the same encoding
        // representation as non-optional Unions (i.e. nullable Unions are
        // inlined).
        break;

      case Decl::Kind::kBits:
      case Decl::Kind::kEnum:
      case Decl::Kind::kTable:
        if (args.nullability == types::Nullability::kNullable)
          return Fail(ErrCannotBeNullable, args.span);
        break;

      case Decl::Kind::kResource: {
        // Currently the only resource types are new-style handles,
        // and they should be resolved to concrete subtypes and
        // dispatched to the handle template earlier.
        assert(false);
        break;
      }

      default:
        if (args.nullability == types::Nullability::kNullable)
          break;
    }

    *out_type = std::make_unique<IdentifierType>(name_, args.nullability, type_decl_);
    return true;
  }

 private:
  Library* library_;
  TypeDecl* type_decl_;
};

class TypeAliasTypeTemplate final : public TypeTemplate {
 public:
  TypeAliasTypeTemplate(Name name, Typespace* typespace, Reporter* reporter, Library* library,
                        TypeAlias* decl)
      : TypeTemplate(std::move(name), typespace, reporter), library_(library), decl_(decl) {}

  bool Create(const CreateInvocation& args, std::unique_ptr<Type>* out_type,
              std::optional<TypeConstructor::FromTypeAlias>* out_from_type_alias) const {
    assert(!args.handle_subtype);
    assert(!args.handle_rights);

    if (!decl_->compiled) {
      assert(!decl_->compiling && "TODO(fxbug.dev/35218): Improve support for recursive types.");

      if (!library_->CompileDecl(decl_)) {
        return Fail(ErrMustBeParameterized, args.span);
      }
    }

    const Type* arg_type = nullptr;
    if (decl_->partial_type_ctor->maybe_arg_type_ctor) {
      if (args.arg_type) {
        return Fail(ErrCannotParametrizeTwice, args.span);
      }
      arg_type = decl_->partial_type_ctor->maybe_arg_type_ctor->type;
    } else {
      arg_type = args.arg_type;
    }

    const Size* size = nullptr;
    if (decl_->partial_type_ctor->maybe_size) {
      if (args.size) {
        return Fail(ErrCannotBoundTwice, args.span);
      }
      size = static_cast<const Size*>(&decl_->partial_type_ctor->maybe_size->Value());
    } else {
      size = args.size;
    }

    std::optional<uint32_t> obj_type;
    std::optional<types::HandleSubtype> handle_subtype;
    if (decl_->partial_type_ctor->handle_subtype_identifier) {
      if (args.handle_subtype) {
        return Fail(ErrCannotParametrizeTwice, args.span);
      }
      obj_type = decl_->partial_type_ctor->handle_obj_type_resolved;
      handle_subtype = decl_->partial_type_ctor->handle_subtype_identifier_resolved;
    } else {
      obj_type = args.obj_type;
      handle_subtype = args.handle_subtype;
    }

    types::Nullability nullability;
    if (decl_->partial_type_ctor->nullability == types::Nullability::kNullable) {
      if (args.nullability == types::Nullability::kNullable) {
        return Fail(ErrCannotIndicateNullabilityTwice, args.span);
      }
      nullability = types::Nullability::kNullable;
    } else {
      nullability = args.nullability;
    }

    if (!typespace_->CreateNotOwned(decl_->partial_type_ctor->name, arg_type, obj_type,
                                    handle_subtype, decl_->partial_type_ctor->handle_rights.get(),
                                    size, nullability, out_type, nullptr))
      return false;
    if (out_from_type_alias)
      *out_from_type_alias = TypeConstructor::FromTypeAlias(decl_, args.arg_type, args.size,
                                                            args.handle_subtype, args.nullability);
    return true;
  }

 private:
  Library* library_;
  TypeAlias* decl_;
};

Typespace Typespace::RootTypes(Reporter* reporter) {
  Typespace root_typespace(reporter);

  auto add_template = [&](std::unique_ptr<TypeTemplate> type_template) {
    const Name& name = type_template->name();
    root_typespace.templates_.emplace(name, std::move(type_template));
  };

  auto add_primitive = [&](const std::string& name, types::PrimitiveSubtype subtype) {
    add_template(std::make_unique<PrimitiveTypeTemplate>(&root_typespace, reporter, name, subtype));
  };

  add_primitive("bool", types::PrimitiveSubtype::kBool);

  add_primitive("int8", types::PrimitiveSubtype::kInt8);
  add_primitive("int16", types::PrimitiveSubtype::kInt16);
  add_primitive("int32", types::PrimitiveSubtype::kInt32);
  add_primitive("int64", types::PrimitiveSubtype::kInt64);
  add_primitive("uint8", types::PrimitiveSubtype::kUint8);
  add_primitive("uint16", types::PrimitiveSubtype::kUint16);
  add_primitive("uint32", types::PrimitiveSubtype::kUint32);
  add_primitive("uint64", types::PrimitiveSubtype::kUint64);

  add_primitive("float32", types::PrimitiveSubtype::kFloat32);
  add_primitive("float64", types::PrimitiveSubtype::kFloat64);

  // TODO(fxbug.dev/7807): Remove when there is generalized support.
  const static auto kByteName = Name::CreateIntrinsic("byte");
  const static auto kBytesName = Name::CreateIntrinsic("bytes");
  root_typespace.templates_.emplace(
      kByteName, std::make_unique<PrimitiveTypeTemplate>(&root_typespace, reporter, "uint8",
                                                         types::PrimitiveSubtype::kUint8));
  root_typespace.templates_.emplace(kBytesName,
                                    std::make_unique<BytesTypeTemplate>(&root_typespace, reporter));

  add_template(std::make_unique<ArrayTypeTemplate>(&root_typespace, reporter));
  add_template(std::make_unique<VectorTypeTemplate>(&root_typespace, reporter));
  add_template(std::make_unique<StringTypeTemplate>(&root_typespace, reporter));
  add_template(std::make_unique<HandleTypeTemplate>(&root_typespace, reporter));
  add_template(std::make_unique<RequestTypeTemplate>(&root_typespace, reporter));

  return root_typespace;
}

AttributeSchema::AttributeSchema(const std::set<Placement>& allowed_placements,
                                 const std::set<std::string> allowed_values, Constraint constraint)
    : allowed_placements_(allowed_placements),
      allowed_values_(allowed_values),
      constraint_(std::move(constraint)) {}

AttributeSchema AttributeSchema::Deprecated() {
  return AttributeSchema({Placement::kDeprecated}, {});
}

void AttributeSchema::ValidatePlacement(Reporter* reporter, const raw::Attribute& attribute,
                                        Placement placement) const {
  if (allowed_placements_.size() == 0)
    return;

  if (allowed_placements_.size() == 1 && *allowed_placements_.cbegin() == Placement::kDeprecated) {
    reporter->Report(ErrDeprecatedAttribute, attribute.span(), attribute);
    return;
  }

  auto iter = allowed_placements_.find(placement);
  if (iter != allowed_placements_.end())
    return;
  reporter->Report(ErrInvalidAttributePlacement, attribute.span(), attribute);
}

void AttributeSchema::ValidateValue(Reporter* reporter, const raw::Attribute& attribute) const {
  if (allowed_values_.size() == 0)
    return;
  auto iter = allowed_values_.find(attribute.value);
  if (iter != allowed_values_.end())
    return;
  reporter->Report(ErrInvalidAttributeValue, attribute.span(), attribute, attribute.value,
                   allowed_values_);
}

void AttributeSchema::ValidateConstraint(Reporter* reporter, const raw::Attribute& attribute,
                                         const Decl* decl) const {
  auto check = reporter->Checkpoint();
  auto passed = constraint_(reporter, attribute, decl);
  if (passed) {
    assert(check.NoNewErrors() && "cannot add errors and pass");
  } else if (check.NoNewErrors()) {
    // TODO(pascallouis): It would be nicer to use the span of
    // the declaration, however we do not keep it around today.
    reporter->Report(ErrAttributeConstraintNotSatisfied, attribute.span(), attribute,
                     attribute.value);
  }
}

bool SimpleLayoutConstraint(Reporter* reporter, const raw::Attribute& attribute, const Decl* decl) {
  assert(decl->kind == Decl::Kind::kStruct);
  auto struct_decl = static_cast<const Struct*>(decl);
  bool ok = true;
  for (const auto& member : struct_decl->members) {
    if (!IsSimple(member.type_ctor.get()->type, reporter)) {
      reporter->Report(ErrMemberMustBeSimple, member.name, member.name.data());
      ok = false;
    }
  }
  return ok;
}

bool ParseBound(Reporter* reporter, const SourceSpan& span, const std::string& input,
                uint32_t* out_value) {
  auto result = utils::ParseNumeric(input, out_value, 10);
  switch (result) {
    case utils::ParseNumericResult::kOutOfBounds:
      reporter->Report(ErrBoundIsTooBig, span);
      return false;
    case utils::ParseNumericResult::kMalformed: {
      reporter->Report(ErrUnableToParseBound, span, input);
      return false;
    }
    case utils::ParseNumericResult::kSuccess:
      return true;
  }
}

bool Library::VerifyInlineSize(const Struct* struct_decl) {
  if (struct_decl->typeshape(WireFormat::kV1NoEe).InlineSize() >= 65536) {
    return Library::Fail(ErrInlineSizeExceeds64k, *struct_decl);
  }
  return true;
}

bool MaxBytesConstraint(Reporter* reporter, const raw::Attribute& attribute, const Decl* decl) {
  uint32_t bound;
  if (!ParseBound(reporter, attribute.span(), attribute.value, &bound))
    return false;
  uint32_t max_bytes = std::numeric_limits<uint32_t>::max();
  switch (decl->kind) {
    case Decl::Kind::kStruct: {
      auto struct_decl = static_cast<const Struct*>(decl);
      max_bytes = struct_decl->typeshape(WireFormat::kV1NoEe).InlineSize() +
                  struct_decl->typeshape(WireFormat::kV1NoEe).MaxOutOfLine();
      break;
    }
    case Decl::Kind::kTable: {
      auto table_decl = static_cast<const Table*>(decl);
      max_bytes = table_decl->typeshape(WireFormat::kV1NoEe).InlineSize() +
                  table_decl->typeshape(WireFormat::kV1NoEe).MaxOutOfLine();
      break;
    }
    case Decl::Kind::kUnion: {
      auto union_decl = static_cast<const Union*>(decl);
      max_bytes = union_decl->typeshape(WireFormat::kV1NoEe).InlineSize() +
                  union_decl->typeshape(WireFormat::kV1NoEe).MaxOutOfLine();
      break;
    }
    default:
      assert(false && "unexpected kind");
      return false;
  }
  if (max_bytes > bound) {
    reporter->Report(ErrTooManyBytes, attribute.span(), bound, max_bytes);
    return false;
  }
  return true;
}

bool MaxHandlesConstraint(Reporter* reporter, const raw::Attribute& attribute, const Decl* decl) {
  uint32_t bound;
  if (!ParseBound(reporter, attribute.span(), attribute.value, &bound))
    return false;
  uint32_t max_handles = std::numeric_limits<uint32_t>::max();
  switch (decl->kind) {
    case Decl::Kind::kStruct: {
      auto struct_decl = static_cast<const Struct*>(decl);
      max_handles = struct_decl->typeshape(WireFormat::kV1NoEe).MaxHandles();
      break;
    }
    case Decl::Kind::kTable: {
      auto table_decl = static_cast<const Table*>(decl);
      max_handles = table_decl->typeshape(WireFormat::kV1NoEe).MaxHandles();
      break;
    }
    case Decl::Kind::kUnion: {
      auto union_decl = static_cast<const Union*>(decl);
      max_handles = union_decl->typeshape(WireFormat::kV1NoEe).MaxHandles();
      break;
    }
    default:
      assert(false && "unexpected kind");
      return false;
  }
  if (max_handles > bound) {
    reporter->Report(ErrTooManyHandles, attribute.span(), bound, max_handles);
    return false;
  }
  return true;
}

bool ResultShapeConstraint(Reporter* reporter, const raw::Attribute& attribute, const Decl* decl) {
  assert(decl->kind == Decl::Kind::kUnion);
  auto union_decl = static_cast<const Union*>(decl);
  assert(union_decl->members.size() == 2);
  auto& error_member = union_decl->members.at(1);
  assert(error_member.maybe_used && "must have an error member");
  auto error_type = error_member.maybe_used->type_ctor->type;

  const PrimitiveType* error_primitive = nullptr;
  if (error_type->kind == Type::Kind::kPrimitive) {
    error_primitive = static_cast<const PrimitiveType*>(error_type);
  } else if (error_type->kind == Type::Kind::kIdentifier) {
    auto identifier_type = static_cast<const IdentifierType*>(error_type);
    if (identifier_type->type_decl->kind == Decl::Kind::kEnum) {
      auto error_enum = static_cast<const Enum*>(identifier_type->type_decl);
      assert(error_enum->subtype_ctor->type->kind == Type::Kind::kPrimitive);
      error_primitive = static_cast<const PrimitiveType*>(error_enum->subtype_ctor->type);
    }
  }

  if (!error_primitive || (error_primitive->subtype != types::PrimitiveSubtype::kInt32 &&
                           error_primitive->subtype != types::PrimitiveSubtype::kUint32)) {
    reporter->Report(ErrInvalidErrorType, decl->name.span());
    return false;
  }

  return true;
}

static std::string Trim(std::string s) {
  s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
            return !utils::IsWhitespace(static_cast<char>(ch));
          }));
  s.erase(std::find_if(s.rbegin(), s.rend(),
                       [](int ch) { return !utils::IsWhitespace(static_cast<char>(ch)); })
              .base(),
          s.end());
  return s;
}

bool TransportConstraint(Reporter* reporter, const raw::Attribute& attribute, const Decl* decl) {
  // Parse comma separated transports
  const std::string& value = attribute.value;
  std::string::size_type prev_pos = 0;
  std::string::size_type pos;
  std::vector<std::string> transports;
  while ((pos = value.find(',', prev_pos)) != std::string::npos) {
    transports.emplace_back(Trim(value.substr(prev_pos, pos - prev_pos)));
    prev_pos = pos + 1;
  }
  transports.emplace_back(Trim(value.substr(prev_pos)));

  // Validate that they're ok

  // function-local static pointer to non-trivially-destructible type
  // is allowed by styleguide
  static const auto kValidTransports = new std::set<std::string>{
      "Banjo",
      "Channel",
      "Syscall",
  };
  for (auto transport : transports) {
    if (kValidTransports->count(transport) == 0) {
      reporter->Report(ErrInvalidTransportType, decl->name.span(), transport, *kValidTransports);
      return false;
    }
  }
  return true;
}

const Resource::Property* Resource::LookupProperty(std::string_view name) {
  for (const Property& property : properties) {
    if (property.name.data() == name.data()) {
      return &property;
    }
  }
  return nullptr;
}

Libraries::Libraries() {
  // clang-format off
  AddAttributeSchema("Discoverable", AttributeSchema({
    AttributeSchema::Placement::kProtocolDecl,
  }, {
    "",
  }));
  AddAttributeSchema("Doc", AttributeSchema({
    /* any placement */
  }, {
    /* any value */
  }));
  AddAttributeSchema("Layout", AttributeSchema::Deprecated()),
  AddAttributeSchema("ForDeprecatedCBindings", AttributeSchema({
    AttributeSchema::Placement::kProtocolDecl,
    AttributeSchema::Placement::kStructDecl,
  }, {
    "",
  },
  SimpleLayoutConstraint));
  AddAttributeSchema("MaxBytes", AttributeSchema({
    AttributeSchema::Placement::kProtocolDecl,
    AttributeSchema::Placement::kMethod,
    AttributeSchema::Placement::kStructDecl,
    AttributeSchema::Placement::kTableDecl,
    AttributeSchema::Placement::kUnionDecl,
  }, {
      /* any value */
  },
  MaxBytesConstraint));
  AddAttributeSchema("MaxHandles", AttributeSchema({
    AttributeSchema::Placement::kProtocolDecl,
    AttributeSchema::Placement::kMethod,
    AttributeSchema::Placement::kStructDecl,
    AttributeSchema::Placement::kTableDecl,
    AttributeSchema::Placement::kUnionDecl,
  }, {
    /* any value */
  },
  MaxHandlesConstraint));
  AddAttributeSchema("Result", AttributeSchema({
    AttributeSchema::Placement::kUnionDecl,
  }, {
      "",
  },
  ResultShapeConstraint));
  AddAttributeSchema("Selector", AttributeSchema({
    AttributeSchema::Placement::kMethod,
  }, {
      /* any value */
  }));
  AddAttributeSchema("Transitional", AttributeSchema({
    AttributeSchema::Placement::kMethod,
    AttributeSchema::Placement::kBitsDecl,
    AttributeSchema::Placement::kEnumDecl,
    AttributeSchema::Placement::kUnionDecl,
  }, {
    /* any value */
  }));
  AddAttributeSchema("Transport", AttributeSchema({
    AttributeSchema::Placement::kProtocolDecl,
  }, {
    /* any value */
  }, TransportConstraint));
  AddAttributeSchema("Unknown", AttributeSchema({
    AttributeSchema::Placement::kEnumMember,
    AttributeSchema::Placement::kUnionMember,
  }, {
    ""
  }));
  // clang-format on
}

bool Libraries::Insert(std::unique_ptr<Library> library) {
  std::vector<std::string_view> library_name = library->name();
  auto iter = all_libraries_.emplace(library_name, std::move(library));
  return iter.second;
}

bool Libraries::Lookup(const std::vector<std::string_view>& library_name,
                       Library** out_library) const {
  auto iter = all_libraries_.find(library_name);
  if (iter == all_libraries_.end()) {
    return false;
  }

  *out_library = iter->second.get();
  return true;
}

std::set<std::vector<std::string_view>> Libraries::Unused(const Library* target_library) const {
  std::set<std::vector<std::string_view>> unused;
  for (auto& name_library : all_libraries_)
    unused.insert(name_library.first);
  unused.erase(target_library->name());
  std::set<const Library*> worklist = {target_library};
  while (worklist.size() != 0) {
    auto it = worklist.begin();
    auto next = *it;
    worklist.erase(it);
    for (const auto dependency : next->dependencies()) {
      unused.erase(dependency->name());
      worklist.insert(dependency);
    }
  }
  return unused;
}

size_t EditDistance(const std::string& sequence1, const std::string& sequence2) {
  size_t s1_length = sequence1.length();
  size_t s2_length = sequence2.length();
  size_t row1[s1_length + 1];
  size_t row2[s1_length + 1];
  size_t* last_row = row1;
  size_t* this_row = row2;
  for (size_t i = 0; i <= s1_length; i++)
    last_row[i] = i;
  for (size_t j = 0; j < s2_length; j++) {
    this_row[0] = j + 1;
    auto s2c = sequence2[j];
    for (size_t i = 1; i <= s1_length; i++) {
      auto s1c = sequence1[i - 1];
      this_row[i] = std::min(std::min(last_row[i] + 1, this_row[i - 1] + 1),
                             last_row[i - 1] + (s1c == s2c ? 0 : 1));
    }
    std::swap(last_row, this_row);
  }
  return last_row[s1_length];
}

const AttributeSchema* Libraries::RetrieveAttributeSchema(Reporter* reporter,
                                                          const raw::Attribute& attribute) const {
  const auto& attribute_name = attribute.name;
  auto iter = attribute_schemas_.find(attribute_name);
  if (iter != attribute_schemas_.end()) {
    const auto& schema = iter->second;
    return &schema;
  }

  // Skip typo check?
  if (reporter == nullptr)
    return nullptr;

  // Match against all known attributes.
  for (const auto& name_and_schema : attribute_schemas_) {
    auto edit_distance = EditDistance(name_and_schema.first, attribute_name);
    if (0 < edit_distance && edit_distance < 2) {
      reporter->Report(WarnAttributeTypo, attribute.span(), attribute_name, name_and_schema.first);
      return nullptr;
    }
  }

  return nullptr;
}

bool Dependencies::Register(const SourceSpan& span, std::string_view filename, Library* dep_library,
                            const std::unique_ptr<raw::Identifier>& maybe_alias) {
  refs_.push_back(std::make_unique<LibraryRef>(span, dep_library));
  auto ref = refs_.back().get();

  auto library_name = dep_library->name();
  if (!InsertByName(filename, library_name, ref)) {
    return false;
  }

  if (maybe_alias) {
    std::vector<std::string_view> alias_name = {maybe_alias->span().data()};
    if (!InsertByName(filename, alias_name, ref)) {
      return false;
    }
  }

  dependencies_aggregate_.insert(dep_library);

  return true;
}

bool Dependencies::InsertByName(std::string_view filename,
                                const std::vector<std::string_view>& name, LibraryRef* ref) {
  auto iter = dependencies_.find(std::string(filename));
  if (iter == dependencies_.end()) {
    dependencies_.emplace(filename, std::make_unique<ByName>());
  }

  iter = dependencies_.find(std::string(filename));
  assert(iter != dependencies_.end());

  auto insert = iter->second->emplace(name, ref);
  return insert.second;
}

bool Dependencies::Contains(std::string_view filename, const std::vector<std::string_view>& name) {
  auto iter1 = dependencies_.find(std::string(filename));
  if (iter1 == dependencies_.end()) {
    return false;
  }

  auto iter2 = iter1->second->find(name);
  return iter2 != iter1->second->end();
}

bool Dependencies::LookupAndUse(std::string_view filename,
                                const std::vector<std::string_view>& name, Library** out_library) {
  auto iter1 = dependencies_.find(std::string(filename));
  if (iter1 == dependencies_.end()) {
    return false;
  }

  auto iter2 = iter1->second->find(name);
  if (iter2 == iter1->second->end()) {
    return false;
  }

  auto ref = iter2->second;
  ref->used_ = true;
  *out_library = ref->library_;
  return true;
}

bool Dependencies::VerifyAllDependenciesWereUsed(const Library& for_library, Reporter* reporter) {
  auto checkpoint = reporter->Checkpoint();
  for (auto by_name_iter = dependencies_.begin(); by_name_iter != dependencies_.end();
       by_name_iter++) {
    const auto& by_name = *by_name_iter->second;
    for (const auto& name_to_ref : by_name) {
      const auto& ref = name_to_ref.second;
      if (ref->used_)
        continue;
      reporter->Report(ErrUnusedImport, ref->span_, for_library.name(), ref->library_->name(),
                       ref->library_->name());
    }
  }
  return checkpoint.NoNewErrors();
}

// Consuming the AST is primarily concerned with walking the tree and
// flattening the representation. The AST's declaration nodes are
// converted into the Library's foo_declaration structures. This means pulling
// a struct declaration inside a protocol out to the top level and
// so on.

std::string LibraryName(const Library* library, std::string_view separator) {
  if (library != nullptr) {
    return StringJoin(library->name(), separator);
  }
  return std::string();
}

bool Library::Fail(std::unique_ptr<Diagnostic> err) {
  assert(err && "should not report nullptr error");
  reporter_->Report(std::move(err));
  return false;
}

template <typename... Args>
bool Library::Fail(const ErrorDef<Args...>& err, const Args&... args) {
  reporter_->Report(err, args...);
  return false;
}

template <typename... Args>
bool Library::Fail(const ErrorDef<Args...>& err, const std::optional<SourceSpan>& span,
                   const Args&... args) {
  reporter_->Report(err, span, args...);
  return false;
}

void Library::ValidateAttributesPlacement(AttributeSchema::Placement placement,
                                          const raw::AttributeList* attributes) {
  if (attributes == nullptr)
    return;
  for (const auto& attribute : attributes->attributes) {
    auto schema = all_libraries_->RetrieveAttributeSchema(reporter_, attribute);
    if (schema != nullptr) {
      schema->ValidatePlacement(reporter_, attribute, placement);
      schema->ValidateValue(reporter_, attribute);
    }
  }
}

void Library::ValidateAttributesConstraints(const Decl* decl,
                                            const raw::AttributeList* attributes) {
  if (attributes == nullptr)
    return;
  for (const auto& attribute : attributes->attributes) {
    auto schema = all_libraries_->RetrieveAttributeSchema(nullptr, attribute);
    if (schema != nullptr)
      schema->ValidateConstraint(reporter_, attribute, decl);
  }
}

SourceSpan Library::GeneratedSimpleName(const std::string& name) {
  return generated_source_file_.AddLine(name);
}

std::string Library::NextAnonymousName() {
  // TODO(fxbug.dev/7920): Improve anonymous name generation. We want to be
  // specific about how these names are generated once they appear in the
  // JSON IR, and are exposed to the backends.
  std::ostringstream data;
  data << "SomeLongAnonymousPrefix";
  data << anon_counter_++;

  return data.str();
}

std::optional<Name> Library::CompileCompoundIdentifier(
    const raw::CompoundIdentifier* compound_identifier) {
  const auto& components = compound_identifier->components;
  assert(components.size() >= 1);

  SourceSpan decl_name = components.back()->span();

  // First try resolving the identifier in the library.
  if (components.size() == 1) {
    return Name::CreateSourced(this, decl_name);
  }

  std::vector<std::string_view> library_name;
  for (auto iter = components.begin(); iter != components.end() - 1; ++iter) {
    library_name.push_back((*iter)->span().data());
  }

  auto filename = compound_identifier->span().source_file().filename();
  Library* dep_library = nullptr;
  if (dependencies_.LookupAndUse(filename, library_name, &dep_library)) {
    return Name::CreateSourced(dep_library, decl_name);
  }

  // If the identifier is not found in the library it might refer to a
  // declaration with a member (e.g. library.EnumX.val or BitsY.val).
  SourceSpan member_name = decl_name;
  SourceSpan member_decl_name = components.rbegin()[1]->span();

  if (components.size() == 2) {
    return Name::CreateSourced(this, member_decl_name, std::string(member_name.data()));
  }

  std::vector<std::string_view> member_library_name(library_name);
  member_library_name.pop_back();

  Library* member_dep_library = nullptr;
  if (dependencies_.LookupAndUse(filename, member_library_name, &member_dep_library)) {
    return Name::CreateSourced(member_dep_library, member_decl_name,
                               std::string(member_name.data()));
  }

  Fail(ErrUnknownDependentLibrary, components[0]->span(), library_name, member_library_name);
  return std::nullopt;
}

namespace {

template <typename T>
void StoreDecl(Decl* decl_ptr, std::vector<std::unique_ptr<T>>* declarations) {
  std::unique_ptr<T> t_decl;
  t_decl.reset(static_cast<T*>(decl_ptr));
  declarations->push_back(std::move(t_decl));
}

}  // namespace

bool Library::RegisterDecl(std::unique_ptr<Decl> decl) {
  assert(decl);

  auto decl_ptr = decl.release();
  auto kind = decl_ptr->kind;
  switch (kind) {
    case Decl::Kind::kBits:
      StoreDecl(decl_ptr, &bits_declarations_);
      break;
    case Decl::Kind::kConst:
      StoreDecl(decl_ptr, &const_declarations_);
      break;
    case Decl::Kind::kEnum:
      StoreDecl(decl_ptr, &enum_declarations_);
      break;
    case Decl::Kind::kProtocol:
      StoreDecl(decl_ptr, &protocol_declarations_);
      break;
    case Decl::Kind::kResource:
      StoreDecl(decl_ptr, &resource_declarations_);
      break;
    case Decl::Kind::kService:
      StoreDecl(decl_ptr, &service_declarations_);
      break;
    case Decl::Kind::kStruct:
      StoreDecl(decl_ptr, &struct_declarations_);
      break;
    case Decl::Kind::kTable:
      StoreDecl(decl_ptr, &table_declarations_);
      break;
    case Decl::Kind::kTypeAlias:
      StoreDecl(decl_ptr, &type_alias_declarations_);
      break;
    case Decl::Kind::kUnion:
      StoreDecl(decl_ptr, &union_declarations_);
      break;
  }  // switch

  const Name& name = decl_ptr->name;
  {
    const auto it = declarations_.emplace(name, decl_ptr);
    if (!it.second) {
      const auto previous_name = it.first->second->name;
      assert(previous_name.span() && "declarations_ has a name with no span");
      return Fail(ErrNameCollision, name.span(), name, *previous_name.span());
    }
  }

  const auto canonical_decl_name = utils::canonicalize(name.decl_name());
  {
    const auto it = declarations_by_canonical_name_.emplace(canonical_decl_name, decl_ptr);
    if (!it.second) {
      const auto previous_name = it.first->second->name;
      assert(previous_name.span() && "declarations_by_canonical_name_ has a name with no span");
      return Fail(ErrNameCollisionCanonical, name.span(), name, previous_name,
                  *previous_name.span(), canonical_decl_name);
    }
  }

  if (name.span()) {
    if (dependencies_.Contains(name.span()->source_file().filename(), {name.span()->data()})) {
      return Fail(ErrDeclNameConflictsWithLibraryImport, name, name);
    }
    if (dependencies_.Contains(name.span()->source_file().filename(), {canonical_decl_name})) {
      return Fail(ErrDeclNameConflictsWithLibraryImportCanonical, name, name, canonical_decl_name);
    }
  }

  switch (kind) {
    case Decl::Kind::kBits:
    case Decl::Kind::kEnum:
    case Decl::Kind::kService:
    case Decl::Kind::kStruct:
    case Decl::Kind::kTable:
    case Decl::Kind::kUnion:
    case Decl::Kind::kProtocol: {
      auto type_decl = static_cast<TypeDecl*>(decl_ptr);
      auto type_template =
          std::make_unique<TypeDeclTypeTemplate>(name, typespace_, reporter_, this, type_decl);
      typespace_->AddTemplate(std::move(type_template));
      break;
    }
    case Decl::Kind::kTypeAlias: {
      auto type_alias_decl = static_cast<TypeAlias*>(decl_ptr);
      auto type_alias_template = std::make_unique<TypeAliasTypeTemplate>(
          name, typespace_, reporter_, this, type_alias_decl);
      typespace_->AddTemplate(std::move(type_alias_template));
      break;
    }
    case Decl::Kind::kConst:
    case Decl::Kind::kResource:
      break;
  }  // switch
  return true;
}

ConsumeStep Library::StartConsumeStep(fidl::utils::Syntax syntax) {
  return ConsumeStep(this, syntax);
}
CompileStep Library::StartCompileStep() { return CompileStep(this); }
VerifyResourcenessStep Library::StartVerifyResourcenessStep() {
  return VerifyResourcenessStep(this);
}
VerifyAttributesStep Library::StartVerifyAttributesStep() { return VerifyAttributesStep(this); }

bool Library::ConsumeConstant(std::unique_ptr<raw::Constant> raw_constant,
                              std::unique_ptr<Constant>* out_constant) {
  switch (raw_constant->kind) {
    case raw::Constant::Kind::kIdentifier: {
      auto identifier = static_cast<raw::IdentifierConstant*>(raw_constant.get());
      auto name = CompileCompoundIdentifier(identifier->identifier.get());
      if (!name)
        return false;
      *out_constant =
          std::make_unique<IdentifierConstant>(std::move(name.value()), identifier->span());
      break;
    }
    case raw::Constant::Kind::kLiteral: {
      auto literal = static_cast<raw::LiteralConstant*>(raw_constant.get());
      *out_constant = std::make_unique<LiteralConstant>(std::move(literal->literal));
      break;
    }
    case raw::Constant::Kind::kBinaryOperator: {
      auto binary_operator_constant = static_cast<raw::BinaryOperatorConstant*>(raw_constant.get());
      BinaryOperatorConstant::Operator op;
      switch (binary_operator_constant->op) {
        case raw::BinaryOperatorConstant::Operator::kOr:
          op = BinaryOperatorConstant::Operator::kOr;
          break;
      }
      std::unique_ptr<Constant> left_operand;
      if (!ConsumeConstant(std::move(binary_operator_constant->left_operand), &left_operand)) {
        return false;
      }
      std::unique_ptr<Constant> right_operand;
      if (!ConsumeConstant(std::move(binary_operator_constant->right_operand), &right_operand)) {
        return false;
      }
      *out_constant = std::make_unique<BinaryOperatorConstant>(
          std::move(left_operand), std::move(right_operand), op, binary_operator_constant->span());
      break;
    }
  }
  return true;
}

bool Library::ConsumeTypeConstructorOld(std::unique_ptr<raw::TypeConstructorOld> raw_type_ctor,
                                        std::unique_ptr<TypeConstructor>* out_type_ctor) {
  auto name = CompileCompoundIdentifier(raw_type_ctor->identifier.get());
  if (!name)
    return false;

  std::unique_ptr<TypeConstructor> maybe_arg_type_ctor;
  if (raw_type_ctor->maybe_arg_type_ctor != nullptr) {
    if (!ConsumeTypeConstructorOld(std::move(raw_type_ctor->maybe_arg_type_ctor),
                                   &maybe_arg_type_ctor))
      return false;
  }

  std::unique_ptr<Constant> maybe_size;
  if (raw_type_ctor->maybe_size != nullptr) {
    if (!ConsumeConstant(std::move(raw_type_ctor->maybe_size), &maybe_size))
      return false;
  }

  std::unique_ptr<Constant> handle_rights;
  if (raw_type_ctor->handle_rights != nullptr) {
    if (!ConsumeConstant(std::move(raw_type_ctor->handle_rights), &handle_rights))
      return false;
  }

  std::optional<Name> handle_subtype_identifier;
  if (raw_type_ctor->handle_subtype_identifier) {
    handle_subtype_identifier =
        Name::CreateSourced(this, raw_type_ctor->handle_subtype_identifier->span());
  }

  *out_type_ctor = std::make_unique<TypeConstructor>(
      std::move(name.value()), std::move(maybe_arg_type_ctor), std::move(handle_subtype_identifier),
      std::move(handle_rights), std::move(maybe_size), raw_type_ctor->nullability,
      fidl::utils::Syntax::kOld);
  return true;
}

void Library::ConsumeUsing(std::unique_ptr<raw::Using> using_directive,
                           fidl::utils::Syntax syntax) {
  if (using_directive->maybe_type_ctor) {
    ConsumeTypeAlias(std::move(using_directive), syntax);
    return;
  }

  if (using_directive->attributes && using_directive->attributes->attributes.size() != 0) {
    Fail(ErrAttributesNotAllowedOnLibraryImport, using_directive->span(),
         *(using_directive->attributes));
    return;
  }

  std::vector<std::string_view> library_name;
  for (const auto& component : using_directive->using_path->components) {
    library_name.push_back(component->span().data());
  }

  Library* dep_library = nullptr;
  if (!all_libraries_->Lookup(library_name, &dep_library)) {
    Fail(ErrUnknownLibrary, using_directive->using_path->components[0]->span(), library_name);
    return;
  }

  auto filename = using_directive->span().source_file().filename();
  if (!dependencies_.Register(using_directive->span(), filename, dep_library,
                              using_directive->maybe_alias)) {
    Fail(ErrDuplicateLibraryImport, library_name);
    return;
  }

  // Import declarations, and type aliases of dependent library.
  const auto& declarations = dep_library->declarations_;
  declarations_.insert(declarations.begin(), declarations.end());
}

bool Library::ConsumeTypeAlias(std::unique_ptr<raw::AliasDeclaration> alias_declaration,
                               fidl::utils::Syntax syntax) {
  assert(alias_declaration->alias && IsTypeConstructorDefined(alias_declaration->type_ctor));

  auto alias_name = Name::CreateSourced(this, alias_declaration->alias->span());
  std::unique_ptr<TypeConstructor> type_ctor_;

  if (!ConsumeTypeConstructor(std::move(alias_declaration->type_ctor), alias_name, &type_ctor_))
    return false;

  return RegisterDecl(std::make_unique<TypeAlias>(std::move(alias_declaration->attributes),
                                                  std::move(alias_name), std::move(type_ctor_),
                                                  false /* allow_partial_type_ctor */));
}

bool Library::ConsumeTypeAlias(std::unique_ptr<raw::Using> using_directive,
                               fidl::utils::Syntax syntax) {
  assert(using_directive->maybe_type_ctor);
  assert(syntax == fidl::utils::Syntax::kOld && "new syntax shouldn't use using aliases");

  auto span = using_directive->using_path->components[0]->span();
  auto alias_name = Name::CreateSourced(this, span);
  std::unique_ptr<TypeConstructor> partial_type_ctor_;
  if (!ConsumeTypeConstructorOld(std::move(using_directive->maybe_type_ctor), &partial_type_ctor_))
    return false;
  return RegisterDecl(std::make_unique<TypeAlias>(
      std::move(using_directive->attributes), std::move(alias_name), std::move(partial_type_ctor_),
      true /* allow_partial_type_ctor */));
}

void Library::ConsumeBitsDeclaration(std::unique_ptr<raw::BitsDeclaration> bits_declaration) {
  std::vector<Bits::Member> members;
  for (auto& member : bits_declaration->members) {
    auto span = member->identifier->span();
    std::unique_ptr<Constant> value;
    if (!ConsumeConstant(std::move(member->value), &value))
      return;
    members.emplace_back(span, std::move(value), std::move(member->attributes));
    // TODO(pascallouis): right now, members are not registered. Look into
    // registering them, potentially under the bits name qualifier such as
    // <name_of_bits>.<name_of_member>.
  }

  std::unique_ptr<TypeConstructor> type_ctor;
  if (bits_declaration->maybe_type_ctor) {
    if (!ConsumeTypeConstructorOld(std::move(bits_declaration->maybe_type_ctor), &type_ctor))
      return;
  } else {
    type_ctor = TypeConstructor::CreateSizeType();
  }

  RegisterDecl(std::make_unique<Bits>(
      std::move(bits_declaration->attributes),
      Name::CreateSourced(this, bits_declaration->identifier->span()), std::move(type_ctor),
      std::move(members), bits_declaration->strictness));
}

void Library::ConsumeConstDeclaration(std::unique_ptr<raw::ConstDeclaration> const_declaration) {
  auto attributes = std::move(const_declaration->attributes);
  auto span = const_declaration->identifier->span();
  auto name = Name::CreateSourced(this, span);
  std::unique_ptr<TypeConstructor> type_ctor;
  // TODO(fxbug.dev/73285): shouldn't need to care about context here
  if (!ConsumeTypeConstructor(std::move(const_declaration->type_ctor), name, &type_ctor))
    return;

  std::unique_ptr<Constant> constant;
  if (!ConsumeConstant(std::move(const_declaration->constant), &constant))
    return;

  RegisterDecl(std::make_unique<Const>(std::move(attributes), std::move(name), std::move(type_ctor),
                                       std::move(constant)));
}

void Library::ConsumeEnumDeclaration(std::unique_ptr<raw::EnumDeclaration> enum_declaration) {
  std::vector<Enum::Member> members;
  for (auto& member : enum_declaration->members) {
    auto span = member->identifier->span();
    std::unique_ptr<Constant> value;
    if (!ConsumeConstant(std::move(member->value), &value))
      return;
    members.emplace_back(span, std::move(value), std::move(member->attributes));
    // TODO(pascallouis): right now, members are not registered. Look into
    // registering them, potentially under the enum name qualifier such as
    // <name_of_enum>.<name_of_member>.
  }

  std::unique_ptr<TypeConstructor> type_ctor;
  if (enum_declaration->maybe_type_ctor) {
    if (!ConsumeTypeConstructorOld(std::move(enum_declaration->maybe_type_ctor), &type_ctor))
      return;
  } else {
    type_ctor = TypeConstructor::CreateSizeType();
  }

  RegisterDecl(std::make_unique<Enum>(
      std::move(enum_declaration->attributes),
      Name::CreateSourced(this, enum_declaration->identifier->span()), std::move(type_ctor),
      std::move(members), enum_declaration->strictness));
}

bool Library::CreateMethodResult(const Name& protocol_name, SourceSpan response_span,
                                 raw::ProtocolMethod* method, Struct* in_response,
                                 fidl::utils::Syntax syntax, Struct** out_response) {
  // Compile the error type.
  std::unique_ptr<TypeConstructor> error_type_ctor;
  if (!ConsumeTypeConstructorOld(std::move(method->maybe_error_ctor), &error_type_ctor))
    return false;

  // Make the Result union containing the response struct and the
  // error type.
  SourceSpan method_name_span = method->identifier->span();

  // TODO(fxbug.dev/8027): Join spans of response and error constructor for `result_name`.
  auto result_name = Name::CreateDerived(
      this, response_span,
      StringJoin({protocol_name.decl_name(), method_name_span.data(), "Result"}, "_"));

  raw::SourceElement sourceElement = raw::SourceElement(fidl::Token(), fidl::Token());
  Union::Member response_member{
      std::make_unique<raw::Ordinal64>(sourceElement, 1),  // success case explicitly has ordinal 1
      IdentifierTypeForDecl(in_response, types::Nullability::kNonnullable, syntax),
      GeneratedSimpleName("response"), nullptr};
  Union::Member error_member{
      std::make_unique<raw::Ordinal64>(sourceElement, 2),  // error case explicitly has ordinal 2
      std::move(error_type_ctor), GeneratedSimpleName("err"), nullptr};
  std::vector<Union::Member> result_members;
  result_members.push_back(std::move(response_member));
  result_members.push_back(std::move(error_member));
  std::vector<raw::Attribute> result_attributes;
  result_attributes.emplace_back(*method, "Result", "");
  auto result_attributelist =
      std::make_unique<raw::AttributeList>(*method, std::move(result_attributes));
  auto union_decl = std::make_unique<Union>(std::move(result_attributelist), std::move(result_name),
                                            std::move(result_members), types::Strictness::kStrict,
                                            std::nullopt /* resourceness */);
  auto result_decl = union_decl.get();
  if (!RegisterDecl(std::move(union_decl)))
    return false;

  // Make a new response struct for the method containing just the
  // result union.
  std::vector<Struct::Member> response_members;
  response_members.push_back(
      Struct::Member(IdentifierTypeForDecl(result_decl, types::Nullability::kNonnullable, syntax),
                     GeneratedSimpleName("result"), nullptr, nullptr));

  auto struct_decl = std::make_unique<Struct>(
      nullptr /* attributes */, Name::CreateDerived(this, response_span, NextAnonymousName()),
      std::move(response_members), std::nullopt /* resourceness */,
      true /* is_request_or_response */);
  auto struct_decl_ptr = struct_decl.get();
  if (!RegisterDecl(std::move(struct_decl)))
    return false;
  *out_response = struct_decl_ptr;
  return true;
}

void Library::ConsumeProtocolDeclaration(
    std::unique_ptr<raw::ProtocolDeclaration> protocol_declaration, fidl::utils::Syntax syntax) {
  auto attributes = std::move(protocol_declaration->attributes);
  auto name = Name::CreateSourced(this, protocol_declaration->identifier->span());

  std::set<Name> composed_protocols;
  for (auto& composed_protocol : protocol_declaration->composed_protocols) {
    auto& protocol_name = composed_protocol->protocol_name;
    auto composed_protocol_name = CompileCompoundIdentifier(protocol_name.get());
    if (!composed_protocol_name)
      return;
    if (!composed_protocols.insert(std::move(composed_protocol_name.value())).second) {
      Fail(ErrProtocolComposedMultipleTimes, composed_protocol_name->span());
      return;
    }
  }

  std::vector<Protocol::Method> methods;
  for (auto& method : protocol_declaration->methods) {
    auto selector =
        fidl::ordinals::GetSelector(method->attributes.get(), method->identifier->span());
    if (!utils::IsValidIdentifierComponent(selector) &&
        !utils::IsValidFullyQualifiedMethodIdentifier(selector)) {
      Fail(ErrInvalidSelectorValue, method->identifier->span());
    }
    auto generated_ordinal64 = std::make_unique<raw::Ordinal64>(
        method_hasher_(library_name_, name.decl_name(), selector, *method->identifier));
    auto attributes = std::move(method->attributes);
    SourceSpan method_name = method->identifier->span();

    Struct* maybe_request = nullptr;
    if (method->maybe_request != nullptr) {
      auto request_span = method->maybe_request->span();
      auto request_name = Name::CreateDerived(this, request_span, NextAnonymousName());
      if (!ConsumeParameterList(std::move(request_name), std::move(method->maybe_request), true,
                                syntax, &maybe_request))
        return;
    }

    Struct* maybe_response = nullptr;
    if (method->maybe_response != nullptr) {
      const bool has_error = (method->maybe_error_ctor != nullptr);

      SourceSpan response_span = method->maybe_response->span();
      Name response_name = Name::CreateDerived(
          this, response_span,
          has_error ? StringJoin({name.decl_name(), method_name.data(), "Response"}, "_")
                    : NextAnonymousName());
      if (!ConsumeParameterList(std::move(response_name), std::move(method->maybe_response),
                                !has_error, syntax, &maybe_response))
        return;

      if (has_error) {
        if (!CreateMethodResult(name, response_span, method.get(), maybe_response, syntax,
                                &maybe_response))
          return;
      }
    }

    assert(maybe_request != nullptr || maybe_response != nullptr);
    methods.emplace_back(std::move(attributes), std::move(generated_ordinal64),
                         std::move(method_name), std::move(maybe_request),
                         std::move(maybe_response));
  }

  RegisterDecl(std::make_unique<Protocol>(std::move(attributes), std::move(name),
                                          std::move(composed_protocols), std::move(methods)));
}

bool Library::ConsumeResourceDeclaration(
    std::unique_ptr<raw::ResourceDeclaration> resource_declaration, fidl::utils::Syntax syntax) {
  auto name = Name::CreateSourced(this, resource_declaration->identifier->span());
  std::vector<Resource::Property> properties;
  for (auto& property : resource_declaration->properties) {
    std::unique_ptr<TypeConstructor> type_ctor;
    auto anonymous_resource_name = Name::CreateDerived(
        this, property->span(),
        std::string(name.decl_name()) + std::string(property->identifier->span().data()));
    if (!ConsumeTypeConstructor(std::move(property->type_ctor), anonymous_resource_name,
                                &type_ctor))
      return false;
    auto attributes = std::move(property->attributes);
    properties.emplace_back(std::move(type_ctor), property->identifier->span(),
                            std::move(attributes));
  }

  std::unique_ptr<TypeConstructor> type_ctor;
  if (raw::IsTypeConstructorDefined(resource_declaration->maybe_type_ctor)) {
    // TODO(fxbug.dev/73285): shouldn't need to care about the naming context here.
    if (!ConsumeTypeConstructor(std::move(resource_declaration->maybe_type_ctor), name, &type_ctor))
      return false;
  } else {
    type_ctor = TypeConstructor::CreateSizeType();
  }

  return RegisterDecl(std::make_unique<Resource>(std::move(resource_declaration->attributes),
                                                 std::move(name), std::move(type_ctor),
                                                 std::move(properties)));
}

std::unique_ptr<TypeConstructor> Library::IdentifierTypeForDecl(const Decl* decl,
                                                                types::Nullability nullability,
                                                                fidl::utils::Syntax syntax) {
  return std::make_unique<TypeConstructor>(decl->name, nullptr /* maybe_arg_type */,
                                           std::optional<Name>() /* handle_subtype_identifier */,
                                           nullptr /* handle_rights */, nullptr /* maybe_size */,
                                           nullability, syntax);
}

bool Library::ConsumeParameterList(Name name, std::unique_ptr<raw::ParameterList> parameter_list,
                                   bool is_request_or_response, fidl::utils::Syntax syntax,
                                   Struct** out_struct_decl) {
  std::vector<Struct::Member> members;
  for (auto& parameter : parameter_list->parameter_list) {
    std::unique_ptr<TypeConstructor> type_ctor;
    // TODO(fxbug.dev/73285): finalize layout naming
    auto param_name = Name::CreateDerived(
        this, parameter->span(),
        std::string(name.decl_name()) +
            utils::to_upper_camel_case(std::string(parameter->identifier->span().data())));
    if (!ConsumeTypeConstructor(std::move(parameter->type_ctor), param_name, &type_ctor))
      return false;
    ValidateAttributesPlacement(AttributeSchema::Placement::kStructMember,
                                parameter->attributes.get());
    members.emplace_back(std::move(type_ctor), parameter->identifier->span(),
                         nullptr /* maybe_default_value */, std::move(parameter->attributes));
  }

  if (!RegisterDecl(std::make_unique<Struct>(nullptr /* attributes */, std::move(name),
                                             std::move(members), std::nullopt /* resourceness */,
                                             is_request_or_response)))
    return false;
  *out_struct_decl = struct_declarations_.back().get();
  return true;
}

void Library::ConsumeServiceDeclaration(std::unique_ptr<raw::ServiceDeclaration> service_decl,
                                        fidl::utils::Syntax syntax) {
  auto attributes = std::move(service_decl->attributes);
  auto name = Name::CreateSourced(this, service_decl->identifier->span());

  std::vector<Service::Member> members;
  for (auto& member : service_decl->members) {
    std::unique_ptr<TypeConstructor> type_ctor;
    // TODO(fxbug.dev/73285): shouldn't need to care about naming context here.
    if (!ConsumeTypeConstructor(std::move(member->type_ctor), name, &type_ctor))
      return;
    members.emplace_back(std::move(type_ctor), member->identifier->span(),
                         std::move(member->attributes));
  }

  RegisterDecl(
      std::make_unique<Service>(std::move(attributes), std::move(name), std::move(members)));
}

void Library::ConsumeStructDeclaration(std::unique_ptr<raw::StructDeclaration> struct_declaration) {
  auto attributes = std::move(struct_declaration->attributes);
  auto name = Name::CreateSourced(this, struct_declaration->identifier->span());

  std::vector<Struct::Member> members;
  for (auto& member : struct_declaration->members) {
    std::unique_ptr<TypeConstructor> type_ctor;
    if (!ConsumeTypeConstructorOld(std::move(member->type_ctor), &type_ctor))
      return;
    std::unique_ptr<Constant> maybe_default_value;
    if (member->maybe_default_value != nullptr) {
      if (!ConsumeConstant(std::move(member->maybe_default_value), &maybe_default_value))
        return;
    }
    auto attributes = std::move(member->attributes);
    members.emplace_back(std::move(type_ctor), member->identifier->span(),
                         std::move(maybe_default_value), std::move(attributes));
  }

  RegisterDecl(std::make_unique<Struct>(std::move(attributes), std::move(name), std::move(members),
                                        struct_declaration->resourceness));
}

void Library::ConsumeTableDeclaration(std::unique_ptr<raw::TableDeclaration> table_declaration) {
  auto attributes = std::move(table_declaration->attributes);
  auto name = Name::CreateSourced(this, table_declaration->identifier->span());

  std::vector<Table::Member> members;
  for (auto& member : table_declaration->members) {
    auto ordinal_literal = std::move(member->ordinal);

    if (member->maybe_used) {
      std::unique_ptr<TypeConstructor> type_ctor;
      if (!ConsumeTypeConstructorOld(std::move(member->maybe_used->type_ctor), &type_ctor))
        return;
      std::unique_ptr<Constant> maybe_default_value;
      if (member->maybe_used->maybe_default_value) {
        // TODO(fxbug.dev/7932): Support defaults on tables.
        const auto default_value = member->maybe_used->maybe_default_value.get();
        reporter_->Report(ErrDefaultsOnTablesNotSupported, default_value->span());
      }
      if (type_ctor->nullability != types::Nullability::kNonnullable) {
        Fail(ErrNullableTableMember, member->span());
        return;
      }
      auto attributes = std::move(member->maybe_used->attributes);
      members.emplace_back(std::move(ordinal_literal), std::move(type_ctor),
                           member->maybe_used->identifier->span(), std::move(maybe_default_value),
                           std::move(attributes));
    } else {
      members.emplace_back(std::move(ordinal_literal), member->span());
    }
  }

  RegisterDecl(std::make_unique<Table>(std::move(attributes), std::move(name), std::move(members),
                                       table_declaration->strictness,
                                       table_declaration->resourceness));
}

void Library::ConsumeUnionDeclaration(std::unique_ptr<raw::UnionDeclaration> union_declaration) {
  auto name = Name::CreateSourced(this, union_declaration->identifier->span());

  assert(!union_declaration->members.empty() && "unions must have at least one member");
  auto union_name =
      std::pair<std::string, std::string_view>(LibraryName(this, "."), name.decl_name());
  std::vector<Union::Member> members;
  for (auto& member : union_declaration->members) {
    auto explicit_ordinal = std::move(member->ordinal);

    if (member->maybe_used) {
      std::unique_ptr<TypeConstructor> type_ctor;
      if (!ConsumeTypeConstructorOld(std::move(member->maybe_used->type_ctor), &type_ctor))
        return;
      if (member->maybe_used->maybe_default_value) {
        const auto default_value = member->maybe_used->maybe_default_value.get();
        reporter_->Report(ErrDefaultsOnUnionsNotSupported, default_value->span());
      }
      if (type_ctor->nullability != types::Nullability::kNonnullable) {
        Fail(ErrNullableUnionMember, member->span());
        return;
      }

      members.emplace_back(std::move(explicit_ordinal), std::move(type_ctor),
                           member->maybe_used->identifier->span(),
                           std::move(member->maybe_used->attributes));
    } else {
      members.emplace_back(std::move(explicit_ordinal), member->span());
    }
  }

  RegisterDecl(std::make_unique<Union>(std::move(union_declaration->attributes), std::move(name),
                                       std::move(members), union_declaration->strictness,
                                       union_declaration->resourceness));
}

// TODO(fxbug.dev/71536): these conversion methods may need to be refactored
//  once the new flat AST lands, and such coercion  is no longer needed.
template <typename T, typename M>
bool Library::ConsumeValueLayout(std::unique_ptr<raw::Layout> layout, const Name& context) {
  std::vector<M> members;
  size_t index = 0;
  for (auto& mem : layout->members) {
    auto member = static_cast<raw::ValueLayoutMember*>(mem.get());
    auto span = member->identifier->span();
    std::unique_ptr<Constant> value;
    if (!ConsumeConstant(std::move(member->value), &value))
      return false;

    members.emplace_back(span, std::move(value), /*attributes=*/nullptr);
    index++;
  }

  std::unique_ptr<TypeConstructor> subtype_ctor;
  if (layout->subtype_ctor != nullptr) {
    if (!ConsumeTypeConstructorNew(std::move(layout->subtype_ctor), context, &subtype_ctor))
      return false;
  } else {
    subtype_ctor = TypeConstructor::CreateSizeType();
  }

  RegisterDecl(std::make_unique<T>(
      /*attributes=*/nullptr, context, std::move(subtype_ctor), std::move(members),
      layout->strictness.value_or(types::Strictness::kFlexible)));
  return true;
}

template <typename T, typename M>
bool Library::ConsumeOrdinaledLayout(std::unique_ptr<raw::Layout> layout, const Name& context) {
  std::vector<M> members;
  for (auto& mem : layout->members) {
    auto member = static_cast<raw::OrdinaledLayoutMember*>(mem.get());
    if (member->reserved) {
      members.emplace_back(std::move(member->ordinal), member->span());
      continue;
    }

    auto name_of_anonymous_layout = Name::CreateDerived(
        this, member->span(),
        std::string(context.decl_name()) +
            utils::to_upper_camel_case(std::string(member->identifier->span().data())));
    std::unique_ptr<TypeConstructor> type_ctor;
    if (!ConsumeTypeConstructorNew(std::move(member->type_ctor), name_of_anonymous_layout,
                                   &type_ctor))
      return false;
    if (type_ctor->nullability != types::Nullability::kNonnullable) {
      // TODO(fxbug.dev/65978): This error message could be more specific.  We
      //  may want to just pass the specific error message as a template arg, or
      //  otherwise handle this sort of validation when compiling.
      Fail(ErrNullableOrdinaledMember, member->span());
      return false;
    }

    members.emplace_back(std::move(member->ordinal), std::move(type_ctor),
                         member->identifier->span(), /*attributes=*/nullptr);
  }

  RegisterDecl(std::make_unique<T>(
      /*attributes=*/nullptr, context, std::move(members),
      layout->strictness.value_or(types::Strictness::kFlexible), layout->resourceness));
  return true;
}

bool Library::ConsumeStructLayout(std::unique_ptr<raw::Layout> layout, const Name& context) {
  std::vector<Struct::Member> members;
  for (auto& mem : layout->members) {
    auto member = static_cast<raw::StructLayoutMember*>(mem.get());
    auto name_of_anonymous_layout = Name::CreateDerived(
        this, member->span(),
        std::string(context.decl_name()) +
            utils::to_upper_camel_case(std::string(member->identifier->span().data())));

    std::unique_ptr<TypeConstructor> type_ctor;
    if (!ConsumeTypeConstructorNew(std::move(member->type_ctor), name_of_anonymous_layout,
                                   &type_ctor))
      return false;

    std::unique_ptr<Constant> default_value;
    if (member->default_value != nullptr) {
      ConsumeConstant(std::move(member->default_value), &default_value);
    }

    members.emplace_back(std::move(type_ctor), member->identifier->span(), std::move(default_value),
                         /*attributes=*/nullptr);
  }

  RegisterDecl(std::make_unique<Struct>(/*attributes=*/nullptr, context, std::move(members),
                                        layout->resourceness));
  return true;
}

bool Library::ConsumeLayout(std::unique_ptr<raw::Layout> layout, const Name& context) {
  switch (layout->kind) {
    case raw::Layout::Kind::kBits: {
      return ConsumeValueLayout<Bits, Bits::Member>(std::move(layout), context);
    }
    case raw::Layout::Kind::kEnum: {
      return ConsumeValueLayout<Enum, Enum::Member>(std::move(layout), context);
    }
    case raw::Layout::Kind::kStruct: {
      return ConsumeStructLayout(std::move(layout), context);
    }
    case raw::Layout::Kind::kTable: {
      return ConsumeOrdinaledLayout<Table, Table::Member>(std::move(layout), context);
    }
    case raw::Layout::Kind::kUnion: {
      return ConsumeOrdinaledLayout<Union, Union::Member>(std::move(layout), context);
    }
  }
  assert(false && "layouts must be of type bits, enum, struct, table, or union");
  return true;
}

bool Library::IsOptionalConstraint(std::unique_ptr<TypeConstructor>& type_ctor,
                                   const std::unique_ptr<raw::Constant>& constant) {
  if (constant->span().data() == "optional") {
    return true;
  }
  return false;
}

bool Library::ConsumeTypeConstructorNew(std::unique_ptr<raw::TypeConstructorNew> raw_type_ctor,
                                        const Name& context,
                                        std::unique_ptr<TypeConstructor>* out_type) {
  auto params = std::move(raw_type_ctor->parameters);
  auto constraints = std::move(raw_type_ctor->constraints);
  size_t num_constraints = constraints == nullptr ? 0 : constraints->items.size();

  if (raw_type_ctor->layout_ref->kind == raw::LayoutReference::Kind::kInline) {
    assert((params == nullptr || params->items.empty()) &&
           "anonymous layouts cannot have type parameters");
    auto inline_ref = static_cast<raw::InlineLayoutReference*>(raw_type_ctor->layout_ref.get());
    if (!ConsumeLayout(std::move(inline_ref->layout), context)) {
      return false;
    }
    auto type_ctor = std::make_unique<TypeConstructor>(
        context,
        /*maybe_arg_type_ctor=*/nullptr,
        /*handle_subtype_identifier=*/std::nullopt,
        /*handle_rights=*/nullptr,
        /*maybe_size=*/nullptr, types::Nullability::kNonnullable, fidl::utils::Syntax::kNew);

    // Inline layouts may only plausibly have one constraints ("optional"), so
    // check it here.
    if (num_constraints > 1) {
      Fail(ErrConstraintsOverflow, type_ctor->name, size_t(1), num_constraints);
    }
    if (num_constraints == 1) {
      if (IsOptionalConstraint(type_ctor, constraints->items[0])) {
        type_ctor->nullability = types::Nullability::kNullable;
      } else {
        Fail(ErrConstraintOptionalMisspelled, type_ctor->name,
             constraints->items[0]->span().data());
        return false;
      }
    }
    if (out_type)
      *out_type = std::move(type_ctor);
    return true;
  }

  auto named_ref = static_cast<raw::NamedLayoutReference*>(raw_type_ctor->layout_ref.get());
  SourceSpan span = named_ref->identifier->span();
  auto last_name_component = named_ref->identifier->components.back()->span().data();
  auto name = CompileCompoundIdentifier(named_ref->identifier.get());
  if (!name)
    return false;

  // Initialize the typector with just a name. The other parameters are filled in below.
  auto type_ctor = std::make_unique<TypeConstructor>(
      std::move(name.value()), nullptr, std::nullopt, nullptr, nullptr,
      types::Nullability::kNonnullable, fidl::utils::Syntax::kNew);

  // TODO(fxbug.dev/71536): this mess will get fixed once the new flat AST lands.
  // Are there type parameters?
  if (params != nullptr && !params->items.empty()) {
    // There are currently only 3 generic types: box<TYPE>, vector<TYPE> and array<TYPE,SIZE>.
    // That means the logic here can be very simple (for now): assume the first type parameter is
    // always a maybe_type_ctor, and the second (if it exists) is a maybe_size.
    auto builtin = span.data();
    std::unique_ptr<raw::LayoutParameter> param;
    if (params->items.size() >= 1) {
      // Because all of the generic types we have today only take at most one nested type, it is
      // okay to pass the name context through like this.  If we ever introduce generic types
      // that take two or more types as parameters (ex: map<K,V>, or allowing things like
      // struct{}<T>), we'll need extend the name contexts we pass down to their respective
      // constructors.
      param = std::move(params->items[0]);
      auto name = Name::CreateDerived(this, span, context.full_name());

      switch (param->kind) {
        case raw::LayoutParameter::Kind::kType: {
          auto type_param = static_cast<raw::TypeLayoutParameter*>(param.get());
          if (!ConsumeTypeConstructorNew(std::move(type_param->type_ctor), name,
                                         &type_ctor->maybe_arg_type_ctor))
            return false;
          break;
        }
        case raw::LayoutParameter::Kind::kAmbiguous: {
          auto type_param = static_cast<raw::AmbiguousLayoutParameter*>(param.get());
          auto inner_name = Name::CreateSourced(this, type_param->identifier->span());
          type_ctor->maybe_arg_type_ctor = std::make_unique<TypeConstructor>(
              inner_name,
              /*maybe_arg_type_ctor=*/nullptr,
              /*handle_subtype_identifier=*/std::nullopt,
              /*handle_rights=*/nullptr,
              /*maybe_size=*/nullptr, types::Nullability::kNonnullable, fidl::utils::Syntax::kNew);
          break;
        }
        case raw::LayoutParameter::Kind::kLiteral: {
          assert(false && "the first type parameter must be a type, not a value");
          break;
        }
      }
    }
    if (builtin == "array" && params->items.size() >= 2) {
      param = std::move(params->items[1]);
      switch (param->kind) {
        case raw::LayoutParameter::Kind::kAmbiguous: {
          auto type_param = static_cast<raw::AmbiguousLayoutParameter*>(param.get());
          type_ctor->maybe_size = std::make_unique<Constant>(Constant::Kind::kIdentifier,
                                                             type_param->identifier->span());
          break;
        }
        case raw::LayoutParameter::Kind::kLiteral: {
          auto type_param = static_cast<raw::LiteralLayoutParameter*>(param.get());
          ConsumeConstant(std::move(type_param->literal), &type_ctor->maybe_size);
          break;
        }
        default: {
          assert(false && "the second type parameter must be a numeric value");
        }
      }
    }
  }

  // The rest of this function deals with properly applying constraints in two
  // contexts: the special "handle" case where constraints must be of the form
  // [HANDLE_SUBTYPE, HANDLE_RIGHTS, OPTIONAL], and the "default" context, which
  // accepts constraints of [SIZE, OPTIONAL].
  // TODO(fxbug.dev/68667): handle client and server end types when they exist.
  // TODO(fxbug.dev/71536): The following code makes one assumption that we may
  //  not want to keep: that the constraint optional cannot be overwritten.  In
  //  other words, even if in a FIDL file "optional" is defined to have some
  //  meaining, we still assume the word "optional" does not inherit that
  //  meaning when used in constraints.  For example, consider this FIDL:
  //
  //    const optional uint8 = 3;
  //    alias foo = vector<bool>:optional; // <- What does this "optional" mean?
  //
  //  While in the future we may like for optional to resolve to "3" in such
  //  cases, for now this override is ignored, and "optional" always means
  //  "optional" in the context of constraints.
  if (last_name_component == "handle") {
    // The parser currently only applies handle-like constraints onto types that
    // specifically end in the word "handle" ("handle" or "zx.handle"), and does
    // not do so to their aliases.  We replicate that behavior here.
    if (num_constraints > 3) {
      Fail(ErrConstraintsOverflow, type_ctor->name, size_t(3), num_constraints);
      return false;
    }
    if (num_constraints == 1) {
      // The lone constraint MUST be either one of a subtype OR an "optional."
      if (IsOptionalConstraint(type_ctor, constraints->items[0])) {
        type_ctor->nullability = types::Nullability::kNullable;
      } else {
        type_ctor->handle_subtype_identifier =
            Name::CreateSourced(this, constraints->items[0]->span());
      }
    } else if (num_constraints == 2) {
      // The first constraint MUST be a subtype, the second MUST be a handle
      // rights OR an "optional."
      type_ctor->handle_subtype_identifier =
          Name::CreateSourced(this, constraints->items[0]->span());
      if (IsOptionalConstraint(type_ctor, constraints->items[1])) {
        type_ctor->nullability = types::Nullability::kNullable;
      } else if (!ConsumeConstant(std::move(constraints->items[1]), &type_ctor->handle_rights)) {
        return false;
      }
    } else if (num_constraints == 3) {
      // The first constraint MUST be a subtype, the second MUST be a handle
      // rights, and the third MUST be an "optional."
      type_ctor->handle_subtype_identifier =
          Name::CreateSourced(this, constraints->items[0]->span());
      if (!ConsumeConstant(std::move(constraints->items[1]), &type_ctor->handle_rights)) {
        return false;
      }
      if (IsOptionalConstraint(type_ctor, constraints->items[2])) {
        type_ctor->nullability = types::Nullability::kNullable;
      } else {
        Fail(ErrConstraintOptionalMisspelled, type_ctor->name,
             constraints->items[2]->span().data());
        return false;
      }
    }
  } else {
    // In the non-handle case, constraints are interpreted to be of the
    // [SIZE, OPTIONAL] format.
    if (num_constraints > 2) {
      Fail(ErrConstraintsOverflow, type_ctor->name, size_t(2), num_constraints);
      return false;
    }
    if (num_constraints == 1) {
      // The lone constraint MUST be either one of a size OR an "optional."
      if (IsOptionalConstraint(type_ctor, constraints->items[0])) {
        type_ctor->nullability = types::Nullability::kNullable;
      } else if (!ConsumeConstant(std::move(constraints->items[0]), &type_ctor->maybe_size)) {
        return false;
      }
    } else if (num_constraints == 2) {
      // The first constraint MUST be a size, the second MUST be "optional."
      if (!ConsumeConstant(std::move(constraints->items[0]), &type_ctor->maybe_size)) {
        return false;
      }
      if (IsOptionalConstraint(type_ctor, constraints->items[1])) {
        type_ctor->nullability = types::Nullability::kNullable;
      } else {
        Fail(ErrConstraintOptionalMisspelled, type_ctor->name,
             constraints->items[1]->span().data());
        return false;
      }
      type_ctor->nullability = types::Nullability::kNullable;
    }
  }

  if (out_type)
    *out_type = std::move(type_ctor);
  return true;
}

bool Library::ConsumeTypeConstructor(raw::TypeConstructor raw_type_ctor, const Name& context,
                                     std::unique_ptr<TypeConstructor>* out_type) {
  return std::visit(fidl::utils::matchers{
                        [&, this](std::unique_ptr<raw::TypeConstructorOld> e) -> bool {
                          return ConsumeTypeConstructorOld(std::move(e), out_type);
                        },
                        [&, this](std::unique_ptr<raw::TypeConstructorNew> e) -> bool {
                          return ConsumeTypeConstructorNew(std::move(e), context, out_type);
                        },
                    },
                    std::move(raw_type_ctor));
}

void Library::ConsumeTypeDecl(std::unique_ptr<raw::TypeDecl> type_decl) {
  auto name = Name::CreateSourced(this, type_decl->identifier->span());
  auto& layout_ref = type_decl->type_ctor->layout_ref;
  if (layout_ref->kind == raw::LayoutReference::Kind::kNamed) {
    auto named_ref = static_cast<raw::NamedLayoutReference*>(layout_ref.get());
    Fail(ErrNewTypesNotAllowed, name, named_ref->span().data());
    return;
  }

  ConsumeTypeConstructorNew(std::move(type_decl->type_ctor), name, nullptr);
}

bool Library::ConsumeFile(std::unique_ptr<raw::File> file) {
  if (file->attributes) {
    ValidateAttributesPlacement(AttributeSchema::Placement::kLibrary, file->attributes.get());
    if (!attributes_) {
      attributes_ = std::move(file->attributes);
    } else {
      AttributesBuilder attributes_builder(reporter_, std::move(attributes_->attributes));
      for (auto& attribute : file->attributes->attributes) {
        if (!attributes_builder.Insert(std::move(attribute)))
          return false;
      }
      attributes_ = std::make_unique<raw::AttributeList>(
          raw::SourceElement(file->attributes->start_, file->attributes->end_),
          attributes_builder.Done());
    }
  }

  // All fidl files in a library should agree on the library name.
  std::vector<std::string_view> new_name;
  for (const auto& part : file->library_name->components) {
    new_name.push_back(part->span().data());
  }
  if (!library_name_.empty()) {
    if (new_name != library_name_) {
      return Fail(ErrFilesDisagreeOnLibraryName, file->library_name->components[0]->span());
    }
  } else {
    library_name_ = new_name;
  }

  auto step = StartConsumeStep(file->syntax);

  auto using_list = std::move(file->using_list);
  for (auto& using_directive : using_list) {
    step.ForUsing(std::move(using_directive));
  }

  auto alias_list = std::move(file->alias_list);
  for (auto& alias_declaration : alias_list) {
    step.ForAliasDeclaration(std::move(alias_declaration));
  }

  auto bits_declaration_list = std::move(file->bits_declaration_list);
  for (auto& bits_declaration : bits_declaration_list) {
    step.ForBitsDeclaration(std::move(bits_declaration));
  }

  auto const_declaration_list = std::move(file->const_declaration_list);
  for (auto& const_declaration : const_declaration_list) {
    step.ForConstDeclaration(std::move(const_declaration));
  }

  auto enum_declaration_list = std::move(file->enum_declaration_list);
  for (auto& enum_declaration : enum_declaration_list) {
    step.ForEnumDeclaration(std::move(enum_declaration));
  }

  auto protocol_declaration_list = std::move(file->protocol_declaration_list);
  for (auto& protocol_declaration : protocol_declaration_list) {
    step.ForProtocolDeclaration(std::move(protocol_declaration));
  }

  auto resource_declaration_list = std::move(file->resource_declaration_list);
  for (auto& resource_declaration : resource_declaration_list) {
    step.ForResourceDeclaration(std::move(resource_declaration));
  }

  auto service_declaration_list = std::move(file->service_declaration_list);
  for (auto& service_declaration : service_declaration_list) {
    step.ForServiceDeclaration(std::move(service_declaration));
  }

  auto struct_declaration_list = std::move(file->struct_declaration_list);
  for (auto& struct_declaration : struct_declaration_list) {
    step.ForStructDeclaration(std::move(struct_declaration));
  }

  auto table_declaration_list = std::move(file->table_declaration_list);
  for (auto& table_declaration : table_declaration_list) {
    step.ForTableDeclaration(std::move(table_declaration));
  }

  auto union_declaration_list = std::move(file->union_declaration_list);
  for (auto& union_declaration : union_declaration_list) {
    step.ForUnionDeclaration(std::move(union_declaration));
  }

  auto type_decls = std::move(file->type_decls);
  for (auto& type_decl : type_decls) {
    step.ForTypeDecl(std::move(type_decl));
  }

  return step.Done();
}

bool Library::ResolveOrOperatorConstant(Constant* constant, const Type* type,
                                        const ConstantValue& left_operand,
                                        const ConstantValue& right_operand) {
  assert(left_operand.kind == right_operand.kind &&
         "left and right operands of or operator must be of the same kind");
  type = TypeResolve(type);
  if (type == nullptr)
    return false;
  if (type->kind != Type::Kind::kPrimitive) {
    return Fail(ErrOrOperatorOnNonPrimitiveValue);
  }
  std::unique_ptr<ConstantValue> left_operand_u64;
  std::unique_ptr<ConstantValue> right_operand_u64;
  if (!left_operand.Convert(ConstantValue::Kind::kUint64, &left_operand_u64))
    return false;
  if (!right_operand.Convert(ConstantValue::Kind::kUint64, &right_operand_u64))
    return false;
  NumericConstantValue<uint64_t> result =
      *static_cast<NumericConstantValue<uint64_t>*>(left_operand_u64.get()) |
      *static_cast<NumericConstantValue<uint64_t>*>(right_operand_u64.get());
  std::unique_ptr<ConstantValue> converted_result;
  if (!result.Convert(ConstantValuePrimitiveKind(static_cast<const PrimitiveType*>(type)->subtype),
                      &converted_result))
    return false;
  constant->ResolveTo(std::move(converted_result));
  return true;
}

bool Library::ResolveConstant(Constant* constant, const Type* type) {
  assert(constant != nullptr);

  // Prevent re-entry.
  if (constant->compiled)
    return constant->IsResolved();
  constant->compiled = true;

  switch (constant->kind) {
    case Constant::Kind::kIdentifier: {
      auto identifier_constant = static_cast<IdentifierConstant*>(constant);
      return ResolveIdentifierConstant(identifier_constant, type);
    }
    case Constant::Kind::kLiteral: {
      auto literal_constant = static_cast<LiteralConstant*>(constant);
      return ResolveLiteralConstant(literal_constant, type);
    }
    case Constant::Kind::kSynthesized: {
      assert(false && "Compiler bug: synthesized constant does not have a resolved value!");
      break;
    }
    case Constant::Kind::kBinaryOperator: {
      auto binary_operator_constant = static_cast<BinaryOperatorConstant*>(constant);
      if (!ResolveConstant(binary_operator_constant->left_operand.get(), type)) {
        return false;
      }
      if (!ResolveConstant(binary_operator_constant->right_operand.get(), type)) {
        return false;
      }
      switch (binary_operator_constant->op) {
        case BinaryOperatorConstant::Operator::kOr: {
          return ResolveOrOperatorConstant(constant, type,
                                           binary_operator_constant->left_operand->Value(),
                                           binary_operator_constant->right_operand->Value());
        }
      }
      assert(false && "Compiler bug: unhandled binary operator");
      break;
    }
  }

  __builtin_unreachable();
}

ConstantValue::Kind Library::ConstantValuePrimitiveKind(
    const types::PrimitiveSubtype primitive_subtype) {
  switch (primitive_subtype) {
    case types::PrimitiveSubtype::kBool:
      return ConstantValue::Kind::kBool;
    case types::PrimitiveSubtype::kInt8:
      return ConstantValue::Kind::kInt8;
    case types::PrimitiveSubtype::kInt16:
      return ConstantValue::Kind::kInt16;
    case types::PrimitiveSubtype::kInt32:
      return ConstantValue::Kind::kInt32;
    case types::PrimitiveSubtype::kInt64:
      return ConstantValue::Kind::kInt64;
    case types::PrimitiveSubtype::kUint8:
      return ConstantValue::Kind::kUint8;
    case types::PrimitiveSubtype::kUint16:
      return ConstantValue::Kind::kUint16;
    case types::PrimitiveSubtype::kUint32:
      return ConstantValue::Kind::kUint32;
    case types::PrimitiveSubtype::kUint64:
      return ConstantValue::Kind::kUint64;
    case types::PrimitiveSubtype::kFloat32:
      return ConstantValue::Kind::kFloat32;
    case types::PrimitiveSubtype::kFloat64:
      return ConstantValue::Kind::kFloat64;
  }
  assert(false && "Compiler bug: unhandled primitive subtype");
}

bool Library::ResolveIdentifierConstant(IdentifierConstant* identifier_constant, const Type* type) {
  assert(TypeCanBeConst(type) &&
         "Compiler bug: resolving identifier constant to non-const-able type!");

  auto decl = LookupDeclByName(identifier_constant->name.memberless_key());
  if (!decl)
    return false;

  if (!CompileDecl(decl)) {
    return false;
  }

  const TypeConstructor* const_type_ctor = nullptr;
  const ConstantValue* const_val = nullptr;
  switch (decl->kind) {
    case Decl::Kind::kConst: {
      auto const_decl = static_cast<Const*>(decl);
      const_type_ctor = const_decl->type_ctor.get();
      const_val = &const_decl->value->Value();
      break;
    }
    case Decl::Kind::kEnum: {
      // If there is no member name, fallthrough to default.
      if (auto member_name = identifier_constant->name.member_name(); member_name) {
        auto enum_decl = static_cast<Enum*>(decl);
        const_type_ctor = enum_decl->subtype_ctor.get();
        for (auto& member : enum_decl->members) {
          if (member.name.data() == member_name) {
            const_val = &member.value->Value();
          }
        }
        if (!const_val) {
          return Fail(ErrUnknownEnumMember, identifier_constant->name.span(),
                      std::string_view(*member_name));
        }
        break;
      }
      [[fallthrough]];
    }
    case Decl::Kind::kBits: {
      // If there is no member name, fallthrough to default.
      if (auto member_name = identifier_constant->name.member_name(); member_name) {
        auto bits_decl = static_cast<Bits*>(decl);
        const_type_ctor = bits_decl->subtype_ctor.get();
        for (auto& member : bits_decl->members) {
          if (member.name.data() == member_name) {
            const_val = &member.value->Value();
          }
        }
        if (!const_val) {
          return Fail(ErrUnknownBitsMember, identifier_constant->name.span(),
                      std::string_view(*member_name));
        }
        break;
      }
      [[fallthrough]];
    }
    default: {
      return Fail(ErrExpectedValueButGotType, identifier_constant->name.span(),
                  identifier_constant);
    }
  }

  assert(const_val && "Compiler bug: did not set const_val");
  assert(const_type_ctor && "Compiler bug: did not set const_type_ctor");

  std::unique_ptr<ConstantValue> resolved_val;
  switch (type->kind) {
    case Type::Kind::kString: {
      if (!TypeIsConvertibleTo(const_type_ctor->type, type))
        goto fail_cannot_convert;

      if (!const_val->Convert(ConstantValue::Kind::kString, &resolved_val))
        goto fail_cannot_convert;
      break;
    }
    case Type::Kind::kPrimitive: {
      auto primitive_type = static_cast<const PrimitiveType*>(type);
      if (!const_val->Convert(ConstantValuePrimitiveKind(primitive_type->subtype), &resolved_val))
        goto fail_cannot_convert;
      break;
    }
    case Type::Kind::kIdentifier: {
      auto identifier_type = static_cast<const IdentifierType*>(type);
      const PrimitiveType* primitive_type;
      switch (identifier_type->type_decl->kind) {
        case Decl::Kind::kEnum: {
          auto enum_decl = static_cast<const Enum*>(identifier_type->type_decl);
          assert(enum_decl->subtype_ctor->type->kind == Type::Kind::kPrimitive);
          primitive_type = static_cast<const PrimitiveType*>(enum_decl->subtype_ctor->type);
          break;
        }
        case Decl::Kind::kBits: {
          auto bits_decl = static_cast<const Bits*>(identifier_type->type_decl);
          assert(bits_decl->subtype_ctor->type->kind == Type::Kind::kPrimitive);
          primitive_type = static_cast<const PrimitiveType*>(bits_decl->subtype_ctor->type);
          break;
        }
        default: {
          assert(false && "Compiler bug: identifier not of const-able type.");
        }
      }

      auto fail_with_mismatched_type = [this, identifier_type](const Name& type_name) {
        return Fail(ErrMismatchedNameTypeAssignment, identifier_type->type_decl->name, type_name);
      };

      switch (decl->kind) {
        case Decl::Kind::kConst: {
          if (const_type_ctor->type->name != identifier_type->type_decl->name)
            return fail_with_mismatched_type(const_type_ctor->type->name);
          break;
        }
        case Decl::Kind::kBits:
        case Decl::Kind::kEnum: {
          if (decl->name != identifier_type->type_decl->name)
            return fail_with_mismatched_type(decl->name);
          break;
        }
        default: {
          assert(false && "Compiler bug: identifier not of const-able type.");
        }
      }

      if (!const_val->Convert(ConstantValuePrimitiveKind(primitive_type->subtype), &resolved_val))
        goto fail_cannot_convert;
      break;
    }
    default: {
      assert(false && "Compiler bug: identifier not of const-able type.");
    }
  }

  identifier_constant->ResolveTo(std::move(resolved_val));
  return true;

fail_cannot_convert:
  return Fail(ErrCannotConvertConstantToType, identifier_constant, const_type_ctor, type);
}

bool Library::ResolveLiteralConstant(LiteralConstant* literal_constant, const Type* type) {
  switch (literal_constant->literal->kind) {
    case raw::Literal::Kind::kString: {
      if (type->kind != Type::Kind::kString)
        goto return_fail;
      auto string_type = static_cast<const StringType*>(type);
      auto string_literal = static_cast<raw::StringLiteral*>(literal_constant->literal.get());
      auto string_data = string_literal->span().data();

      // TODO(pascallouis): because data() contains the raw content,
      // with the two " to identify strings, we need to take this
      // into account. We should expose the actual size of string
      // literals properly, and take into account escaping.
      uint64_t string_size = string_data.size() - 2;
      if (string_type->max_size->value < string_size) {
        return Fail(ErrStringConstantExceedsSizeBound, literal_constant->literal->span(),
                    literal_constant, string_size, type);
      }

      literal_constant->ResolveTo(
          std::make_unique<StringConstantValue>(string_literal->span().data()));
      return true;
    }
    case raw::Literal::Kind::kTrue: {
      if (type->kind != Type::Kind::kPrimitive)
        goto return_fail;
      if (static_cast<const PrimitiveType*>(type)->subtype != types::PrimitiveSubtype::kBool)
        goto return_fail;
      literal_constant->ResolveTo(std::make_unique<BoolConstantValue>(true));
      return true;
    }
    case raw::Literal::Kind::kFalse: {
      if (type->kind != Type::Kind::kPrimitive)
        goto return_fail;
      if (static_cast<const PrimitiveType*>(type)->subtype != types::PrimitiveSubtype::kBool)
        goto return_fail;
      literal_constant->ResolveTo(std::make_unique<BoolConstantValue>(false));
      return true;
    }
    case raw::Literal::Kind::kNumeric: {
      if (type->kind != Type::Kind::kPrimitive)
        goto return_fail;

      // These must be initialized out of line to allow for goto statement
      const raw::NumericLiteral* numeric_literal;
      const PrimitiveType* primitive_type;
      numeric_literal = static_cast<const raw::NumericLiteral*>(literal_constant->literal.get());
      primitive_type = static_cast<const PrimitiveType*>(type);
      switch (primitive_type->subtype) {
        case types::PrimitiveSubtype::kInt8: {
          int8_t value;
          if (!ParseNumericLiteral<int8_t>(numeric_literal, &value))
            goto return_fail;
          literal_constant->ResolveTo(std::make_unique<NumericConstantValue<int8_t>>(value));
          return true;
        }
        case types::PrimitiveSubtype::kInt16: {
          int16_t value;
          if (!ParseNumericLiteral<int16_t>(numeric_literal, &value))
            goto return_fail;

          literal_constant->ResolveTo(std::make_unique<NumericConstantValue<int16_t>>(value));
          return true;
        }
        case types::PrimitiveSubtype::kInt32: {
          int32_t value;
          if (!ParseNumericLiteral<int32_t>(numeric_literal, &value))
            goto return_fail;

          literal_constant->ResolveTo(std::make_unique<NumericConstantValue<int32_t>>(value));
          return true;
        }
        case types::PrimitiveSubtype::kInt64: {
          int64_t value;
          if (!ParseNumericLiteral<int64_t>(numeric_literal, &value))
            goto return_fail;

          literal_constant->ResolveTo(std::make_unique<NumericConstantValue<int64_t>>(value));
          return true;
        }
        case types::PrimitiveSubtype::kUint8: {
          uint8_t value;
          if (!ParseNumericLiteral<uint8_t>(numeric_literal, &value))
            goto return_fail;

          literal_constant->ResolveTo(std::make_unique<NumericConstantValue<uint8_t>>(value));
          return true;
        }
        case types::PrimitiveSubtype::kUint16: {
          uint16_t value;
          if (!ParseNumericLiteral<uint16_t>(numeric_literal, &value))
            goto return_fail;

          literal_constant->ResolveTo(std::make_unique<NumericConstantValue<uint16_t>>(value));
          return true;
        }
        case types::PrimitiveSubtype::kUint32: {
          uint32_t value;
          if (!ParseNumericLiteral<uint32_t>(numeric_literal, &value))
            goto return_fail;

          literal_constant->ResolveTo(std::make_unique<NumericConstantValue<uint32_t>>(value));
          return true;
        }
        case types::PrimitiveSubtype::kUint64: {
          uint64_t value;
          if (!ParseNumericLiteral<uint64_t>(numeric_literal, &value))
            goto return_fail;

          literal_constant->ResolveTo(std::make_unique<NumericConstantValue<uint64_t>>(value));
          return true;
        }
        case types::PrimitiveSubtype::kFloat32: {
          float value;
          if (!ParseNumericLiteral<float>(numeric_literal, &value))
            goto return_fail;
          literal_constant->ResolveTo(std::make_unique<NumericConstantValue<float>>(value));
          return true;
        }
        case types::PrimitiveSubtype::kFloat64: {
          double value;
          if (!ParseNumericLiteral<double>(numeric_literal, &value))
            goto return_fail;

          literal_constant->ResolveTo(std::make_unique<NumericConstantValue<double>>(value));
          return true;
        }
        default:
          goto return_fail;
      }

    return_fail:
      return Fail(ErrConstantCannotBeInterpretedAsType, literal_constant->literal->span(),
                  literal_constant, type);
    }
  }
}

const Type* Library::TypeResolve(const Type* type) {
  if (type->kind != Type::Kind::kIdentifier) {
    return type;
  }
  auto identifier_type = static_cast<const IdentifierType*>(type);
  Decl* decl = LookupDeclByName(identifier_type->name);
  if (!decl) {
    Fail(ErrCouldNotResolveIdentifierToType);
    return nullptr;
  }
  if (!CompileDecl(decl))
    return nullptr;
  switch (decl->kind) {
    case Decl::Kind::kBits:
      return static_cast<const Bits*>(decl)->subtype_ctor->type;
    case Decl::Kind::kEnum:
      return static_cast<const Enum*>(decl)->subtype_ctor->type;
    default:
      return type;
  }
}

bool Library::TypeCanBeConst(const Type* type) {
  switch (type->kind) {
    case flat::Type::Kind::kString:
      return type->nullability != types::Nullability::kNullable;
    case flat::Type::Kind::kPrimitive:
      return true;
    case flat::Type::Kind::kIdentifier: {
      auto identifier_type = static_cast<const IdentifierType*>(type);
      switch (identifier_type->type_decl->kind) {
        case Decl::Kind::kEnum:
        case Decl::Kind::kBits:
          return true;
        default:
          return false;
      }
    }
    default:
      return false;
  }  // switch
}

bool Library::TypeIsConvertibleTo(const Type* from_type, const Type* to_type) {
  switch (to_type->kind) {
    case flat::Type::Kind::kString: {
      if (from_type->kind != flat::Type::Kind::kString)
        return false;

      auto from_string_type = static_cast<const flat::StringType*>(from_type);
      auto to_string_type = static_cast<const flat::StringType*>(to_type);

      if (to_string_type->nullability == types::Nullability::kNonnullable &&
          from_string_type->nullability != types::Nullability::kNonnullable)
        return false;

      if (to_string_type->max_size->value < from_string_type->max_size->value)
        return false;

      return true;
    }
    case flat::Type::Kind::kPrimitive: {
      if (from_type->kind != flat::Type::Kind::kPrimitive) {
        return false;
      }

      auto from_primitive_type = static_cast<const flat::PrimitiveType*>(from_type);
      auto to_primitive_type = static_cast<const flat::PrimitiveType*>(to_type);

      switch (to_primitive_type->subtype) {
        case types::PrimitiveSubtype::kBool:
          return from_primitive_type->subtype == types::PrimitiveSubtype::kBool;
        default:
          // TODO(pascallouis): be more precise about convertibility, e.g. it
          // should not be allowed to convert a float to an int.
          return from_primitive_type->subtype != types::PrimitiveSubtype::kBool;
      }
    }
    default:
      return false;
  }  // switch
}

// Library resolution is concerned with resolving identifiers to their
// declarations, and with computing type sizes and alignments.

Decl* Library::LookupDeclByName(Name::Key name) const {
  auto iter = declarations_.find(name);
  if (iter == declarations_.end()) {
    return nullptr;
  }
  return iter->second;
}

const Libraries* Library::GetLibraries() const { return all_libraries_; }

template <typename NumericType>
bool Library::ParseNumericLiteral(const raw::NumericLiteral* literal,
                                  NumericType* out_value) const {
  assert(literal != nullptr);
  assert(out_value != nullptr);

  auto data = literal->span().data();
  std::string string_data(data.data(), data.data() + data.size());
  auto result = utils::ParseNumeric(string_data, out_value);
  return result == utils::ParseNumericResult::kSuccess;
}

bool Library::AddConstantDependencies(const Constant* constant, std::set<Decl*>* out_edges) {
  switch (constant->kind) {
    case Constant::Kind::kIdentifier: {
      auto identifier = static_cast<const flat::IdentifierConstant*>(constant);
      auto decl = LookupDeclByName(identifier->name.memberless_key());
      if (decl == nullptr) {
        return Fail(ErrFailedConstantLookup, identifier->name, identifier->name);
      }
      out_edges->insert(decl);
      break;
    }
    case Constant::Kind::kLiteral:
    case Constant::Kind::kSynthesized: {
      // Literal and synthesized constants have no dependencies on other declarations.
      break;
    }
    case Constant::Kind::kBinaryOperator: {
      auto op = static_cast<const flat::BinaryOperatorConstant*>(constant);
      return AddConstantDependencies(op->left_operand.get(), out_edges) &&
             AddConstantDependencies(op->right_operand.get(), out_edges);
    }
  }
  return true;
}

// Calculating declaration dependencies is largely serving the C/C++ family of languages bindings.
// For instance, the declaration of a struct member type must be defined before the containing
// struct if that member is stored inline.
// Given the FIDL declarations:
//
//     struct D2 { D1 d; }
//     struct D1 { int32 x; }
//
// We must first declare D1, followed by D2 when emitting C code.
//
// Below, an edge from D1 to D2 means that we must see the declaration of of D1 before
// the declaration of D2, i.e. the calculated set of |out_edges| represents all the declarations
// that |decl| depends on.
//
// Notes:
// - Nullable structs do not require dependency edges since they are boxed via a
// pointer indirection, and their content placed out-of-line.
bool Library::DeclDependencies(Decl* decl, std::set<Decl*>* out_edges) {
  std::set<Decl*> edges;
  auto maybe_add_decl = [this, &edges](const TypeConstructor* type_ctor) {
    for (;;) {
      const auto& name = type_ctor->name;
      if (name.decl_name() == "request") {
        return;
      } else if (type_ctor->maybe_arg_type_ctor) {
        type_ctor = type_ctor->maybe_arg_type_ctor.get();
      } else if (type_ctor->nullability == types::Nullability::kNullable) {
        return;
      } else {
        if (auto decl = LookupDeclByName(name); decl && decl->kind != Decl::Kind::kProtocol) {
          edges.insert(decl);
        }
        return;
      }
    }
  };
  switch (decl->kind) {
    case Decl::Kind::kBits: {
      auto bits_decl = static_cast<const Bits*>(decl);
      maybe_add_decl(bits_decl->subtype_ctor.get());
      for (const auto& member : bits_decl->members) {
        if (!AddConstantDependencies(member.value.get(), &edges)) {
          return false;
        }
      }
      break;
    }
    case Decl::Kind::kConst: {
      auto const_decl = static_cast<const Const*>(decl);
      maybe_add_decl(const_decl->type_ctor.get());
      if (!AddConstantDependencies(const_decl->value.get(), &edges)) {
        return false;
      }
      break;
    }
    case Decl::Kind::kEnum: {
      auto enum_decl = static_cast<const Enum*>(decl);
      maybe_add_decl(enum_decl->subtype_ctor.get());
      for (const auto& member : enum_decl->members) {
        if (!AddConstantDependencies(member.value.get(), &edges)) {
          return false;
        }
      }
      break;
    }
    case Decl::Kind::kProtocol: {
      auto protocol_decl = static_cast<const Protocol*>(decl);
      for (const auto& composed_protocol : protocol_decl->composed_protocols) {
        if (auto type_decl = LookupDeclByName(composed_protocol); type_decl) {
          edges.insert(type_decl);
        }
      }
      for (const auto& method : protocol_decl->methods) {
        if (method.maybe_request != nullptr) {
          edges.insert(method.maybe_request);
        }
        if (method.maybe_response != nullptr) {
          edges.insert(method.maybe_response);
        }
      }
      break;
    }
    case Decl::Kind::kResource: {
      auto resource_decl = static_cast<const Resource*>(decl);
      maybe_add_decl(resource_decl->subtype_ctor.get());
      break;
    }
    case Decl::Kind::kService: {
      auto service_decl = static_cast<const Service*>(decl);
      for (const auto& member : service_decl->members) {
        maybe_add_decl(member.type_ctor.get());
      }
      break;
    }
    case Decl::Kind::kStruct: {
      auto struct_decl = static_cast<const Struct*>(decl);
      for (const auto& member : struct_decl->members) {
        maybe_add_decl(member.type_ctor.get());
        if (member.maybe_default_value) {
          if (!AddConstantDependencies(member.maybe_default_value.get(), &edges)) {
            return false;
          }
        }
      }
      break;
    }
    case Decl::Kind::kTable: {
      auto table_decl = static_cast<const Table*>(decl);
      for (const auto& member : table_decl->members) {
        if (!member.maybe_used)
          continue;
        maybe_add_decl(member.maybe_used->type_ctor.get());
        if (member.maybe_used->maybe_default_value) {
          if (!AddConstantDependencies(member.maybe_used->maybe_default_value.get(), &edges)) {
            return false;
          }
        }
      }
      break;
    }
    case Decl::Kind::kUnion: {
      auto union_decl = static_cast<const Union*>(decl);
      for (const auto& member : union_decl->members) {
        if (!member.maybe_used)
          continue;
        maybe_add_decl(member.maybe_used->type_ctor.get());
      }
      break;
    }
    case Decl::Kind::kTypeAlias: {
      auto type_alias_decl = static_cast<const TypeAlias*>(decl);
      maybe_add_decl(type_alias_decl->partial_type_ctor.get());
    }
  }  // switch
  *out_edges = std::move(edges);
  return true;
}

namespace {
// Declaration comparator.
//
// (1) To compare two Decl's in the same library, it suffices to compare the
//     unqualified names of the Decl's. (This is faster.)
//
// (2) To compare two Decl's across libraries, we rely on the fully qualified
//     names of the Decl's. (This is slower.)
struct CmpDeclInLibrary {
  bool operator()(const Decl* a, const Decl* b) const {
    assert(a->name != b->name || a == b);
    const Library* a_library = a->name.library();
    const Library* b_library = b->name.library();
    if (a_library != b_library) {
      return NameFlatName(a->name) < NameFlatName(b->name);
    } else {
      return a->name.decl_name() < b->name.decl_name();
    }
  }
};
}  // namespace

bool Library::SortDeclarations() {
  // |degree| is the number of undeclared dependencies for each decl.
  std::map<Decl*, uint32_t, CmpDeclInLibrary> degrees;
  // |inverse_dependencies| records the decls that depend on each decl.
  std::map<Decl*, std::vector<Decl*>, CmpDeclInLibrary> inverse_dependencies;
  for (auto& name_and_decl : declarations_) {
    Decl* decl = name_and_decl.second;
    std::set<Decl*> deps;
    if (!DeclDependencies(decl, &deps))
      return false;
    degrees[decl] = static_cast<uint32_t>(deps.size());
    for (Decl* dep : deps) {
      inverse_dependencies[dep].push_back(decl);
    }
  }

  // Start with all decls that have no incoming edges.
  std::vector<Decl*> decls_without_deps;
  for (const auto& decl_and_degree : degrees) {
    if (decl_and_degree.second == 0u) {
      decls_without_deps.push_back(decl_and_degree.first);
    }
  }

  while (!decls_without_deps.empty()) {
    // Pull one out of the queue.
    auto decl = decls_without_deps.back();
    decls_without_deps.pop_back();
    assert(degrees[decl] == 0u);
    declaration_order_.push_back(decl);

    // Decrement the incoming degree of all the other decls it
    // points to.
    auto& inverse_deps = inverse_dependencies[decl];
    for (Decl* inverse_dep : inverse_deps) {
      uint32_t& degree = degrees[inverse_dep];
      assert(degree != 0u);
      degree -= 1;
      if (degree == 0u)
        decls_without_deps.push_back(inverse_dep);
    }
  }

  if (declaration_order_.size() != degrees.size()) {
    // We didn't visit all the edges! There was a cycle.
    return Fail(ErrIncludeCycle);
  }

  return true;
}

bool Library::CompileDecl(Decl* decl) {
  if (decl->compiled)
    return true;
  Compiling guard(decl);
  switch (decl->kind) {
    case Decl::Kind::kBits: {
      auto bits_decl = static_cast<Bits*>(decl);
      if (!CompileBits(bits_decl))
        return false;
      break;
    }
    case Decl::Kind::kConst: {
      auto const_decl = static_cast<Const*>(decl);
      if (!CompileConst(const_decl))
        return false;
      break;
    }
    case Decl::Kind::kEnum: {
      auto enum_decl = static_cast<Enum*>(decl);
      if (!CompileEnum(enum_decl))
        return false;
      break;
    }
    case Decl::Kind::kProtocol: {
      auto protocol_decl = static_cast<Protocol*>(decl);
      if (!CompileProtocol(protocol_decl))
        return false;
      break;
    }
    case Decl::Kind::kResource: {
      auto resource_decl = static_cast<Resource*>(decl);
      if (!CompileResource(resource_decl))
        return false;
      break;
    }
    case Decl::Kind::kService: {
      auto service_decl = static_cast<Service*>(decl);
      if (!CompileService(service_decl))
        return false;
      break;
    }
    case Decl::Kind::kStruct: {
      auto struct_decl = static_cast<Struct*>(decl);
      if (!CompileStruct(struct_decl))
        return false;
      break;
    }
    case Decl::Kind::kTable: {
      auto table_decl = static_cast<Table*>(decl);
      if (!CompileTable(table_decl))
        return false;
      break;
    }
    case Decl::Kind::kUnion: {
      auto union_decl = static_cast<Union*>(decl);
      if (!CompileUnion(union_decl))
        return false;
      break;
    }
    case Decl::Kind::kTypeAlias: {
      auto type_alias_decl = static_cast<TypeAlias*>(decl);
      if (!CompileTypeAlias(type_alias_decl))
        return false;
      break;
    }
  }  // switch
  return true;
}

void Library::VerifyDeclAttributes(Decl* decl) {
  assert(decl->compiled && "verification must happen after compilation of decls");
  auto placement_ok = reporter_->Checkpoint();
  switch (decl->kind) {
    case Decl::Kind::kBits: {
      auto bits_declaration = static_cast<Bits*>(decl);
      // Attributes: check placement.
      ValidateAttributesPlacement(AttributeSchema::Placement::kBitsDecl,
                                  bits_declaration->attributes.get());
      for (const auto& member : bits_declaration->members) {
        ValidateAttributesPlacement(AttributeSchema::Placement::kBitsMember,
                                    member.attributes.get());
      }
      if (placement_ok.NoNewErrors()) {
        // Attributes: check constraints.
        ValidateAttributesConstraints(bits_declaration, bits_declaration->attributes.get());
      }
      break;
    }
    case Decl::Kind::kConst: {
      auto const_decl = static_cast<Const*>(decl);
      // Attributes: for const declarations, we only check placement.
      ValidateAttributesPlacement(AttributeSchema::Placement::kConstDecl,
                                  const_decl->attributes.get());
      break;
    }
    case Decl::Kind::kEnum: {
      auto enum_declaration = static_cast<Enum*>(decl);
      // Attributes: check placement.
      ValidateAttributesPlacement(AttributeSchema::Placement::kEnumDecl,
                                  enum_declaration->attributes.get());
      for (const auto& member : enum_declaration->members) {
        ValidateAttributesPlacement(AttributeSchema::Placement::kEnumMember,
                                    member.attributes.get());
      }
      if (placement_ok.NoNewErrors()) {
        // Attributes: check constraints.
        ValidateAttributesConstraints(enum_declaration, enum_declaration->attributes.get());
      }
      break;
    }
    case Decl::Kind::kProtocol: {
      auto protocol_declaration = static_cast<Protocol*>(decl);
      // Attributes: check placement.
      ValidateAttributesPlacement(AttributeSchema::Placement::kProtocolDecl,
                                  protocol_declaration->attributes.get());
      for (const auto& method_with_info : protocol_declaration->all_methods) {
        ValidateAttributesPlacement(AttributeSchema::Placement::kMethod,
                                    method_with_info.method->attributes.get());
      }
      if (placement_ok.NoNewErrors()) {
        // Attributes: check constraints.
        for (const auto method_with_info : protocol_declaration->all_methods) {
          const auto& method = *method_with_info.method;
          if (method.maybe_request) {
            ValidateAttributesConstraints(method.maybe_request,
                                          protocol_declaration->attributes.get());
            ValidateAttributesConstraints(method.maybe_request, method.attributes.get());
          }
          if (method.maybe_response) {
            ValidateAttributesConstraints(method.maybe_response,
                                          protocol_declaration->attributes.get());
            ValidateAttributesConstraints(method.maybe_response, method.attributes.get());
          }
        }
      }
      break;
    }
    case Decl::Kind::kResource: {
      auto resource_declaration = static_cast<Resource*>(decl);
      // Attributes: check placement.
      ValidateAttributesPlacement(AttributeSchema::Placement::kResourceDecl,
                                  resource_declaration->attributes.get());
      for (const auto& property : resource_declaration->properties) {
        ValidateAttributesPlacement(AttributeSchema::Placement::kResourceProperty,
                                    property.attributes.get());
      }
      if (placement_ok.NoNewErrors()) {
        // Attributes: check constraints.
        ValidateAttributesConstraints(resource_declaration, resource_declaration->attributes.get());
      }
      break;
    }
    case Decl::Kind::kService: {
      auto service_decl = static_cast<Service*>(decl);
      // Attributes: check placement.
      ValidateAttributesPlacement(AttributeSchema::Placement::kServiceDecl,
                                  service_decl->attributes.get());
      for (const auto& member : service_decl->members) {
        ValidateAttributesPlacement(AttributeSchema::Placement::kServiceMember,
                                    member.attributes.get());
      }
      if (placement_ok.NoNewErrors()) {
        // Attributes: check constraint.
        ValidateAttributesConstraints(service_decl, service_decl->attributes.get());
      }
      break;
    }
    case Decl::Kind::kStruct: {
      auto struct_declaration = static_cast<Struct*>(decl);
      // Attributes: check placement.
      ValidateAttributesPlacement(AttributeSchema::Placement::kStructDecl,
                                  struct_declaration->attributes.get());
      for (const auto& member : struct_declaration->members) {
        ValidateAttributesPlacement(AttributeSchema::Placement::kStructMember,
                                    member.attributes.get());
      }
      if (placement_ok.NoNewErrors()) {
        // Attributes: check constraint.
        ValidateAttributesConstraints(struct_declaration, struct_declaration->attributes.get());
      }
      break;
    }
    case Decl::Kind::kTable: {
      auto table_declaration = static_cast<Table*>(decl);
      // Attributes: check placement.
      ValidateAttributesPlacement(AttributeSchema::Placement::kTableDecl,
                                  table_declaration->attributes.get());
      for (const auto& member : table_declaration->members) {
        if (!member.maybe_used)
          continue;
        ValidateAttributesPlacement(AttributeSchema::Placement::kTableMember,
                                    member.maybe_used->attributes.get());
      }
      if (placement_ok.NoNewErrors()) {
        // Attributes: check constraint.
        ValidateAttributesConstraints(table_declaration, table_declaration->attributes.get());
      }
      break;
    }
    case Decl::Kind::kUnion: {
      auto union_declaration = static_cast<Union*>(decl);
      // Attributes: check placement.
      ValidateAttributesPlacement(AttributeSchema::Placement::kUnionDecl,
                                  union_declaration->attributes.get());
      for (const auto& member : union_declaration->members) {
        if (!member.maybe_used)
          continue;
        ValidateAttributesPlacement(AttributeSchema::Placement::kUnionMember,
                                    member.maybe_used->attributes.get());
      }
      if (placement_ok.NoNewErrors()) {
        // Attributes: check constraint.
        ValidateAttributesConstraints(union_declaration, union_declaration->attributes.get());
      }
      break;
    }
    case Decl::Kind::kTypeAlias: {
      auto type_alias_declaration = static_cast<TypeAlias*>(decl);
      // Attributes: check placement.
      ValidateAttributesPlacement(AttributeSchema::Placement::kTypeAliasDecl,
                                  type_alias_declaration->attributes.get());
      if (placement_ok.NoNewErrors()) {
        // Attributes: check constraints.
        ValidateAttributesConstraints(type_alias_declaration,
                                      type_alias_declaration->attributes.get());
      }
      break;
    }
  }  // switch
}

void VerifyResourcenessStep::ForDecl(const Decl* decl) {
  assert(decl->compiled && "verification must happen after compilation of decls");
  switch (decl->kind) {
    case Decl::Kind::kStruct: {
      const auto* struct_decl = static_cast<const Struct*>(decl);
      if (struct_decl->resourceness == types::Resourceness::kValue) {
        for (const auto& member : struct_decl->members) {
          if (EffectiveResourceness(member.type_ctor->type) == types::Resourceness::kResource) {
            library_->reporter_->Report(ErrTypeMustBeResource, struct_decl->name.span(),
                                        struct_decl->name, member.name.data(),
                                        std::string_view("struct"), struct_decl->name);
          }
        }
      }
      break;
    }
    case Decl::Kind::kTable: {
      const auto* table_decl = static_cast<const Table*>(decl);
      if (table_decl->resourceness == types::Resourceness::kValue) {
        for (const auto& member : table_decl->members) {
          if (member.maybe_used) {
            const auto& used = *member.maybe_used;
            if (EffectiveResourceness(used.type_ctor->type) == types::Resourceness::kResource) {
              library_->reporter_->Report(ErrTypeMustBeResource, table_decl->name.span(),
                                          table_decl->name, used.name.data(),
                                          std::string_view("table"), table_decl->name);
            }
          }
        }
      }
      break;
    }
    case Decl::Kind::kUnion: {
      const auto* union_decl = static_cast<const Union*>(decl);
      if (union_decl->resourceness == types::Resourceness::kValue) {
        for (const auto& member : union_decl->members) {
          if (member.maybe_used) {
            const auto& used = *member.maybe_used;
            if (EffectiveResourceness(used.type_ctor->type) == types::Resourceness::kResource) {
              library_->reporter_->Report(ErrTypeMustBeResource, union_decl->name.span(),
                                          union_decl->name, used.name.data(),
                                          std::string_view("union"), union_decl->name);
            }
          }
        }
      }
      break;
    }
    default:
      break;
  }
}

types::Resourceness Type::Resourceness() const {
  switch (this->kind) {
    case Type::Kind::kPrimitive:
    case Type::Kind::kString:
      return types::Resourceness::kValue;
    case Type::Kind::kHandle:
    case Type::Kind::kRequestHandle:
      return types::Resourceness::kResource;
    case Type::Kind::kArray:
      return static_cast<const ArrayType*>(this)->element_type->Resourceness();
    case Type::Kind::kVector:
      return static_cast<const VectorType*>(this)->element_type->Resourceness();
    case Type::Kind::kIdentifier:
      break;
  }

  auto decl = static_cast<const IdentifierType*>(this)->type_decl;
  switch (decl->kind) {
    case Decl::Kind::kBits:
    case Decl::Kind::kEnum:
      return types::Resourceness::kValue;
    case Decl::Kind::kProtocol:
      return types::Resourceness::kResource;
    case Decl::Kind::kStruct:
      assert(decl->compiled && "Compiler bug: accessing resourceness of not-yet-compiled struct");
      return static_cast<const Struct*>(decl)->resourceness.value();
    case Decl::Kind::kTable:
      return static_cast<const Table*>(decl)->resourceness;
    case Decl::Kind::kUnion:
      assert(decl->compiled && "Compiler bug: accessing resourceness of not-yet-compiled union");
      return static_cast<const Union*>(decl)->resourceness.value();
    case Decl::Kind::kConst:
    case Decl::Kind::kResource:
    case Decl::Kind::kService:
    case Decl::Kind::kTypeAlias:
      assert(false && "Compiler bug: unexpected kind");
  }

  __builtin_unreachable();
}

types::Resourceness VerifyResourcenessStep::EffectiveResourceness(const Type* type) {
  switch (type->kind) {
    case Type::Kind::kPrimitive:
    case Type::Kind::kString:
      return types::Resourceness::kValue;
    case Type::Kind::kHandle:
    case Type::Kind::kRequestHandle:
      return types::Resourceness::kResource;
    case Type::Kind::kArray:
      return EffectiveResourceness(static_cast<const ArrayType*>(type)->element_type);
    case Type::Kind::kVector:
      return EffectiveResourceness(static_cast<const VectorType*>(type)->element_type);
    case Type::Kind::kIdentifier:
      break;
  }

  auto decl = static_cast<const IdentifierType*>(type)->type_decl;
  switch (decl->kind) {
    case Decl::Kind::kBits:
    case Decl::Kind::kEnum:
      return types::Resourceness::kValue;
    case Decl::Kind::kProtocol:
      return types::Resourceness::kResource;
    case Decl::Kind::kStruct:
      if (static_cast<const Struct*>(decl)->resourceness.value() ==
          types::Resourceness::kResource) {
        return types::Resourceness::kResource;
      }
      break;
    case Decl::Kind::kTable:
      if (static_cast<const Table*>(decl)->resourceness == types::Resourceness::kResource) {
        return types::Resourceness::kResource;
      }
      break;
    case Decl::Kind::kUnion:
      if (static_cast<const Union*>(decl)->resourceness.value() == types::Resourceness::kResource) {
        return types::Resourceness::kResource;
      }
      break;
    case Decl::Kind::kService:
      return types::Resourceness::kValue;
    case Decl::Kind::kConst:
    case Decl::Kind::kResource:
    case Decl::Kind::kTypeAlias:
      assert(false && "Compiler bug: unexpected kind");
  }

  const auto [it, inserted] = effective_resourceness_.try_emplace(decl, std::nullopt);
  if (!inserted) {
    const auto& maybe_value = it->second;
    // If we already computed effective resourceness, return it. If we started
    // computing it but did not complete (nullopt), we're in a cycle, so return
    // kValue as the default assumption.
    return maybe_value.value_or(types::Resourceness::kValue);
  }

  switch (decl->kind) {
    case Decl::Kind::kStruct:
      for (const auto& member : static_cast<const Struct*>(decl)->members) {
        if (EffectiveResourceness(member.type_ctor->type) == types::Resourceness::kResource) {
          effective_resourceness_[decl] = types::Resourceness::kResource;
          return types::Resourceness::kResource;
        }
      }
      break;
    case Decl::Kind::kTable:
      for (const auto& member : static_cast<const Table*>(decl)->members) {
        const auto& used = member.maybe_used;
        if (used &&
            EffectiveResourceness(used->type_ctor->type) == types::Resourceness::kResource) {
          effective_resourceness_[decl] = types::Resourceness::kResource;
          return types::Resourceness::kResource;
        }
      }
      break;
    case Decl::Kind::kUnion:
      for (const auto& member : static_cast<const Union*>(decl)->members) {
        const auto& used = member.maybe_used;
        if (used &&
            EffectiveResourceness(used->type_ctor->type) == types::Resourceness::kResource) {
          effective_resourceness_[decl] = types::Resourceness::kResource;
          return types::Resourceness::kResource;
        }
      }
      break;
    default:
      assert(false && "Compiler bug: unexpected kind");
  }

  effective_resourceness_[decl] = types::Resourceness::kValue;
  return types::Resourceness::kValue;
}

bool Library::CompileBits(Bits* bits_declaration) {
  if (!CompileTypeConstructor(bits_declaration->subtype_ctor.get()))
    return false;

  if (bits_declaration->subtype_ctor->type->kind != Type::Kind::kPrimitive) {
    return Fail(ErrBitsTypeMustBeUnsignedIntegralPrimitive, *bits_declaration,
                bits_declaration->subtype_ctor->type);
  }

  // Validate constants.
  auto primitive_type = static_cast<const PrimitiveType*>(bits_declaration->subtype_ctor->type);
  switch (primitive_type->subtype) {
    case types::PrimitiveSubtype::kUint8: {
      uint8_t mask;
      if (!ValidateBitsMembersAndCalcMask<uint8_t>(bits_declaration, &mask))
        return false;
      bits_declaration->mask = mask;
      break;
    }
    case types::PrimitiveSubtype::kUint16: {
      uint16_t mask;
      if (!ValidateBitsMembersAndCalcMask<uint16_t>(bits_declaration, &mask))
        return false;
      bits_declaration->mask = mask;
      break;
    }
    case types::PrimitiveSubtype::kUint32: {
      uint32_t mask;
      if (!ValidateBitsMembersAndCalcMask<uint32_t>(bits_declaration, &mask))
        return false;
      bits_declaration->mask = mask;
      break;
    }
    case types::PrimitiveSubtype::kUint64: {
      uint64_t mask;
      if (!ValidateBitsMembersAndCalcMask<uint64_t>(bits_declaration, &mask))
        return false;
      bits_declaration->mask = mask;
      break;
    }
    case types::PrimitiveSubtype::kBool:
    case types::PrimitiveSubtype::kInt8:
    case types::PrimitiveSubtype::kInt16:
    case types::PrimitiveSubtype::kInt32:
    case types::PrimitiveSubtype::kInt64:
    case types::PrimitiveSubtype::kFloat32:
    case types::PrimitiveSubtype::kFloat64:
      return Fail(ErrBitsTypeMustBeUnsignedIntegralPrimitive, *bits_declaration,
                  bits_declaration->subtype_ctor->type);
  }

  {
    // In the line below, `nullptr` needs an explicit cast to the pointer type due to
    // C++ template mechanics.
    auto err = ValidateUnknownConstraints<const Bits::Member>(
        *bits_declaration, bits_declaration->strictness, nullptr);
    if (err) {
      return Fail(std::move(err));
    }
  }

  return true;
}

bool Library::CompileConst(Const* const_declaration) {
  if (!CompileTypeConstructor(const_declaration->type_ctor.get()))
    return false;
  const auto* const_type = const_declaration->type_ctor.get()->type;
  if (!TypeCanBeConst(const_type)) {
    return Fail(ErrInvalidConstantType, *const_declaration, const_type);
  }
  if (!ResolveConstant(const_declaration->value.get(), const_type))
    return Fail(ErrCannotResolveConstantValue, *const_declaration);

  return true;
}

bool Library::CompileEnum(Enum* enum_declaration) {
  if (!CompileTypeConstructor(enum_declaration->subtype_ctor.get()))
    return false;

  if (enum_declaration->subtype_ctor->type->kind != Type::Kind::kPrimitive) {
    return Fail(ErrEnumTypeMustBeIntegralPrimitive, *enum_declaration,
                enum_declaration->subtype_ctor->type);
  }

  // Validate constants.
  auto primitive_type = static_cast<const PrimitiveType*>(enum_declaration->subtype_ctor->type);
  enum_declaration->type = primitive_type;
  switch (primitive_type->subtype) {
    case types::PrimitiveSubtype::kInt8: {
      int8_t unknown_value;
      if (!ValidateEnumMembersAndCalcUnknownValue<int8_t>(enum_declaration, &unknown_value))
        return false;
      enum_declaration->unknown_value_signed = unknown_value;
      break;
    }
    case types::PrimitiveSubtype::kInt16: {
      int16_t unknown_value;
      if (!ValidateEnumMembersAndCalcUnknownValue<int16_t>(enum_declaration, &unknown_value))
        return false;
      enum_declaration->unknown_value_signed = unknown_value;
      break;
    }
    case types::PrimitiveSubtype::kInt32: {
      int32_t unknown_value;
      if (!ValidateEnumMembersAndCalcUnknownValue<int32_t>(enum_declaration, &unknown_value))
        return false;
      enum_declaration->unknown_value_signed = unknown_value;
      break;
    }
    case types::PrimitiveSubtype::kInt64: {
      int64_t unknown_value;
      if (!ValidateEnumMembersAndCalcUnknownValue<int64_t>(enum_declaration, &unknown_value))
        return false;
      enum_declaration->unknown_value_signed = unknown_value;
      break;
    }
    case types::PrimitiveSubtype::kUint8: {
      uint8_t unknown_value;
      if (!ValidateEnumMembersAndCalcUnknownValue<uint8_t>(enum_declaration, &unknown_value))
        return false;
      enum_declaration->unknown_value_unsigned = unknown_value;
      break;
    }
    case types::PrimitiveSubtype::kUint16: {
      uint16_t unknown_value;
      if (!ValidateEnumMembersAndCalcUnknownValue<uint16_t>(enum_declaration, &unknown_value))
        return false;
      enum_declaration->unknown_value_unsigned = unknown_value;
      break;
    }
    case types::PrimitiveSubtype::kUint32: {
      uint32_t unknown_value;
      if (!ValidateEnumMembersAndCalcUnknownValue<uint32_t>(enum_declaration, &unknown_value))
        return false;
      enum_declaration->unknown_value_unsigned = unknown_value;
      break;
    }
    case types::PrimitiveSubtype::kUint64: {
      uint64_t unknown_value;
      if (!ValidateEnumMembersAndCalcUnknownValue<uint64_t>(enum_declaration, &unknown_value))
        return false;
      enum_declaration->unknown_value_unsigned = unknown_value;
      break;
    }
    case types::PrimitiveSubtype::kBool:
    case types::PrimitiveSubtype::kFloat32:
    case types::PrimitiveSubtype::kFloat64:
      return Fail(ErrEnumTypeMustBeIntegralPrimitive, *enum_declaration,
                  enum_declaration->subtype_ctor->type);
  }

  return true;
}

bool HasSimpleLayout(const Decl* decl) { return decl->HasAttribute("ForDeprecatedCBindings"); }

bool Library::CompileResource(Resource* resource_declaration) {
  Scope<std::string_view> scope;
  if (!CompileTypeConstructor(resource_declaration->subtype_ctor.get()))
    return false;

  if (resource_declaration->subtype_ctor->type->kind != Type::Kind::kPrimitive) {
    return Fail(ErrEnumTypeMustBeIntegralPrimitive, *resource_declaration,
                resource_declaration->subtype_ctor->type);
  }

  for (auto& property : resource_declaration->properties) {
    auto name_result = scope.Insert(property.name.data(), property.name);
    if (!name_result.ok())
      return Fail(ErrDuplicateResourcePropertyName, property.name,
                  name_result.previous_occurrence());

    if (!CompileTypeConstructor(property.type_ctor.get()))
      return false;
  }
  return true;
}

bool Library::CompileProtocol(Protocol* protocol_declaration) {
  MethodScope method_scope;
  auto CheckScopes = [this, &protocol_declaration, &method_scope](const Protocol* protocol,
                                                                  auto Visitor) -> bool {
    for (const auto& name : protocol->composed_protocols) {
      auto decl = LookupDeclByName(name);
      // TODO(fxbug.dev/7926): Special handling here should not be required, we
      // should first rely on creating the types representing composed
      // protocols.
      if (!decl) {
        return Fail(ErrUnknownType, name, name);
      }
      if (decl->kind != Decl::Kind::kProtocol)
        return Fail(ErrComposingNonProtocol, name);
      auto composed_protocol = static_cast<const Protocol*>(decl);
      auto span = composed_protocol->name.span();
      assert(span);
      if (method_scope.protocols.Insert(composed_protocol, span.value()).ok()) {
        if (!Visitor(composed_protocol, Visitor))
          return false;
      } else {
        // Otherwise we have already seen this protocol in
        // the inheritance graph.
      }
    }
    for (const auto& method : protocol->methods) {
      const auto original_name = method.name.data();
      const auto canonical_name = utils::canonicalize(original_name);
      const auto name_result = method_scope.canonical_names.Insert(canonical_name, method.name);
      if (!name_result.ok()) {
        if (original_name == name_result.previous_occurrence().data()) {
          return Fail(ErrDuplicateMethodName, method.name, original_name,
                      name_result.previous_occurrence());
        }
        const auto previous_span = name_result.previous_occurrence();
        return Fail(ErrDuplicateMethodNameCanonical, method.name, original_name,
                    previous_span.data(), previous_span, canonical_name);
      }
      if (method.generated_ordinal64->value == 0)
        return Fail(ErrGeneratedZeroValueOrdinal, method.generated_ordinal64->span());
      auto ordinal_result =
          method_scope.ordinals.Insert(method.generated_ordinal64->value, method.name);
      if (!ordinal_result.ok()) {
        std::string replacement_method(
            fidl::ordinals::GetSelector(method.attributes.get(), method.name));
        replacement_method.push_back('_');
        return Fail(ErrDuplicateMethodOrdinal, method.generated_ordinal64->span(),
                    ordinal_result.previous_occurrence(), replacement_method);
      }

      // Add a pointer to this method to the protocol_declarations list.
      bool is_composed = protocol_declaration != protocol;
      protocol_declaration->all_methods.emplace_back(&method, is_composed);
    }
    return true;
  };
  if (!CheckScopes(protocol_declaration, CheckScopes))
    return false;

  for (auto& method : protocol_declaration->methods) {
    if (method.maybe_request) {
      if (!CompileDecl(method.maybe_request))
        return false;
    }
    if (method.maybe_response) {
      if (!CompileDecl(method.maybe_response))
        return false;
    }
  }

  return true;
}

bool Library::CompileService(Service* service_decl) {
  Scope<std::string> scope;
  for (const auto& member : service_decl->members) {
    const auto original_name = member.name.data();
    const auto canonical_name = utils::canonicalize(original_name);
    const auto name_result = scope.Insert(canonical_name, member.name);
    if (!name_result.ok()) {
      const auto previous_span = name_result.previous_occurrence();
      if (original_name == name_result.previous_occurrence().data()) {
        return Fail(ErrDuplicateServiceMemberName, member.name, original_name, previous_span);
      }
      return Fail(ErrDuplicateServiceMemberNameCanonical, member.name, original_name,
                  previous_span.data(), previous_span, canonical_name);
    }
    // TODO: in the new syntax we check that the service member is a type, but
    // don't validate that it's client_end or server_end (because they don't exist yet)
    auto expected_category = member.type_ctor->syntax == fidl::utils::Syntax::kOld
                                 ? AllowedCategories::kProtocolOnly
                                 : AllowedCategories::kTypeOnly;
    if (!CompileTypeConstructorAllowing(member.type_ctor.get(), expected_category))
      return false;
    if (member.type_ctor->nullability != types::Nullability::kNonnullable)
      return Fail(ErrNullableServiceMember, member.name);
  }
  return true;
}

bool Library::CompileStruct(Struct* struct_declaration) {
  Scope<std::string> scope;
  DeriveResourceness derive_resourceness(&struct_declaration->resourceness);
  for (const auto& member : struct_declaration->members) {
    const auto original_name = member.name.data();
    const auto canonical_name = utils::canonicalize(original_name);
    const auto name_result = scope.Insert(canonical_name, member.name);
    if (!name_result.ok()) {
      const auto previous_span = name_result.previous_occurrence();
      if (original_name == previous_span.data()) {
        return Fail(struct_declaration->is_request_or_response ? ErrDuplicateMethodParameterName
                                                               : ErrDuplicateStructMemberName,
                    member.name, original_name, previous_span);
      }
      return Fail(struct_declaration->is_request_or_response
                      ? ErrDuplicateMethodParameterNameCanonical
                      : ErrDuplicateStructMemberNameCanonical,
                  member.name, original_name, previous_span.data(), previous_span, canonical_name);
    }

    if (!CompileTypeConstructor(member.type_ctor.get()))
      return false;
    assert(!(struct_declaration->is_request_or_response && member.maybe_default_value) &&
           "method parameters cannot have default values");
    if (member.maybe_default_value) {
      const auto* default_value_type = member.type_ctor->type;
      if (!TypeCanBeConst(default_value_type)) {
        return Fail(ErrInvalidStructMemberType, *struct_declaration, NameIdentifier(member.name),
                    default_value_type);
      }
      if (!ResolveConstant(member.maybe_default_value.get(), default_value_type)) {
        return false;
      }
    }
    derive_resourceness.AddType(member.type_ctor->type);
  }

  return true;
}

bool Library::CompileTable(Table* table_declaration) {
  Scope<std::string> name_scope;
  Ordinal64Scope ordinal_scope;

  for (const auto& member : table_declaration->members) {
    const auto ordinal_result = ordinal_scope.Insert(member.ordinal->value, member.ordinal->span());
    if (!ordinal_result.ok()) {
      return Fail(ErrDuplicateTableFieldOrdinal, member.ordinal->span(),
                  ordinal_result.previous_occurrence());
    }
    if (member.maybe_used) {
      const auto& member_used = *member.maybe_used;
      const auto original_name = member_used.name.data();
      const auto canonical_name = utils::canonicalize(original_name);
      const auto name_result = name_scope.Insert(canonical_name, member_used.name);
      if (!name_result.ok()) {
        const auto previous_span = name_result.previous_occurrence();
        if (original_name == name_result.previous_occurrence().data()) {
          return Fail(ErrDuplicateTableFieldName, member_used.name, original_name, previous_span);
        }
        return Fail(ErrDuplicateTableFieldNameCanonical, member_used.name, original_name,
                    previous_span.data(), previous_span, canonical_name);
      }
      if (!CompileTypeConstructor(member_used.type_ctor.get())) {
        return false;
      }
    }
  }

  if (auto ordinal_and_loc = FindFirstNonDenseOrdinal(ordinal_scope)) {
    auto [ordinal, span] = *ordinal_and_loc;
    return Fail(ErrNonDenseOrdinal, span, ordinal);
  }

  return true;
}

bool Library::CompileUnion(Union* union_declaration) {
  Scope<std::string> scope;
  Ordinal64Scope ordinal_scope;
  DeriveResourceness derive_resourceness(&union_declaration->resourceness);

  for (const auto& member : union_declaration->members) {
    const auto ordinal_result = ordinal_scope.Insert(member.ordinal->value, member.ordinal->span());
    if (!ordinal_result.ok()) {
      return Fail(ErrDuplicateUnionMemberOrdinal, member.ordinal->span(),
                  ordinal_result.previous_occurrence());
    }
    if (member.maybe_used) {
      const auto& member_used = *member.maybe_used;
      const auto original_name = member_used.name.data();
      const auto canonical_name = utils::canonicalize(original_name);
      const auto name_result = scope.Insert(canonical_name, member_used.name);
      if (!name_result.ok()) {
        const auto previous_span = name_result.previous_occurrence();
        if (original_name == name_result.previous_occurrence().data()) {
          return Fail(ErrDuplicateUnionMemberName, member_used.name, original_name, previous_span);
        }
        return Fail(ErrDuplicateUnionMemberNameCanonical, member_used.name, original_name,
                    previous_span.data(), previous_span, canonical_name);
      }

      if (!CompileTypeConstructor(member_used.type_ctor.get())) {
        return false;
      }
      derive_resourceness.AddType(member_used.type_ctor->type);
    }
  }

  if (auto ordinal_and_loc = FindFirstNonDenseOrdinal(ordinal_scope)) {
    auto [ordinal, span] = *ordinal_and_loc;
    return Fail(ErrNonDenseOrdinal, span, ordinal);
  }

  {
    std::vector<const Union::Member::Used*> used_members;
    for (const auto& member : union_declaration->members) {
      if (member.maybe_used)
        used_members.push_back(member.maybe_used.get());
    }

    auto err = ValidateUnknownConstraints(*union_declaration, union_declaration->strictness,
                                          &used_members);
    if (err) {
      return Fail(std::move(err));
    }
  }

  return true;
}

bool Library::CompileTypeAlias(TypeAlias* decl) {
  // Since type aliases can have partial type constructors, it's not always
  // possible to compile them based solely on their declaration.
  //
  // For instance, we might have
  //
  //     using alias = vector:5;
  //
  //  which is only valid on use `alias<string>`.
  //
  // We temporarily disable error reporting, and attempt to compile the
  // partial type constructor.
  bool partial_type_ctor_compiled = false;
  {
    auto temporary_mode = reporter_->OverrideMode(decl->allow_partial_type_ctor
                                                      ? Reporter::ReportingMode::kDoNotReport
                                                      : Reporter::ReportingMode::kReport);
    partial_type_ctor_compiled = CompileTypeConstructor(decl->partial_type_ctor.get());
    if (!decl->allow_partial_type_ctor && !partial_type_ctor_compiled) {
      return false;
    }
  }
  if (decl->partial_type_ctor->maybe_arg_type_ctor && !partial_type_ctor_compiled) {
    if (!CompileTypeConstructor(decl->partial_type_ctor->maybe_arg_type_ctor.get()))
      return false;
  }
  return ResolveSizeBound(decl->partial_type_ctor.get(), nullptr /* out_size */);
}

bool Library::Compile() {
  if (!SortDeclarations()) {
    return false;
  }

  // We process declarations in topologically sorted order. For
  // example, we process a struct member's type before the entire
  // struct.
  auto compile_step = StartCompileStep();
  for (Decl* decl : declaration_order_) {
    compile_step.ForDecl(decl);
  }
  if (!compile_step.Done())
    return false;

  auto verify_resourceness_step = StartVerifyResourcenessStep();
  for (Decl* decl : declaration_order_) {
    verify_resourceness_step.ForDecl(decl);
  }
  if (!verify_resourceness_step.Done())
    return false;

  auto verify_attributes_step = StartVerifyAttributesStep();
  for (Decl* decl : declaration_order_) {
    verify_attributes_step.ForDecl(decl);
  }
  if (!verify_attributes_step.Done())
    return false;

  for (Decl* decl : declaration_order_) {
    if (decl->kind == Decl::Kind::kStruct) {
      auto struct_decl = static_cast<const Struct*>(decl);
      if (!VerifyInlineSize(struct_decl)) {
        return false;
      }
    }
  }

  if (!dependencies_.VerifyAllDependenciesWereUsed(*this, reporter_))
    return false;

  return reporter_->errors().size() == 0;
}

bool Library::CompileTypeConstructor(TypeConstructor* type_ctor) {
  if (type_ctor->syntax == fidl::utils::Syntax::kNew) {
    return CompileTypeConstructorAllowing(type_ctor, AllowedCategories::kTypeOnly);
  }
  return CompileTypeConstructorAllowing(type_ctor, AllowedCategories::kTypeOrProtocol);
}

bool Library::CompileTypeConstructorAllowing(TypeConstructor* type_ctor,
                                             AllowedCategories category) {
  const Type* maybe_arg_type = nullptr;
  if (type_ctor->maybe_arg_type_ctor != nullptr) {
    if (!CompileTypeConstructor(type_ctor->maybe_arg_type_ctor.get()))
      return false;
    maybe_arg_type = type_ctor->maybe_arg_type_ctor->type;
  }
  const Size* size = nullptr;
  if (!ResolveSizeBound(type_ctor, &size)) {
    return false;
  }

  std::optional<types::HandleSubtype> handle_subtype;
  if (type_ctor->handle_subtype_identifier) {
    if (!ResolveHandleSubtypeIdentifier(type_ctor, &type_ctor->handle_obj_type_resolved,
                                        &type_ctor->handle_subtype_identifier_resolved)) {
      return Fail(ErrCouldNotResolveHandleSubtype, type_ctor->name.span(),
                  type_ctor->handle_subtype_identifier.value());
    }
    handle_subtype = type_ctor->handle_subtype_identifier_resolved;
  } else {
    // TODO(fxbug.dev/64629): We need to allow setting a default obj_type in
    // resource_definition declarations rather than hard-coding.
    type_ctor->handle_obj_type_resolved = static_cast<uint32_t>(types::HandleSubtype::kHandle);
  }
  std::optional<uint32_t> obj_type = type_ctor->handle_obj_type_resolved;

  if (type_ctor->handle_rights)
    if (!ResolveHandleRightsConstant(type_ctor))
      return Fail(ErrCouldNotResolveHandleRights);

  if (!typespace_->Create(type_ctor->name, maybe_arg_type, obj_type, handle_subtype,
                          type_ctor->handle_rights.get(), size, type_ctor->nullability,
                          &type_ctor->type, &type_ctor->from_type_alias))
    return false;

  // postcondition: compilation sets the Type of the TypeConstructor
  assert(type_ctor->type && "type constructors' type not resolved after compilation");
  return VerifyTypeCategory(type_ctor, category);
}

bool Library::VerifyTypeCategory(TypeConstructor* type_ctor, AllowedCategories category) {
  assert(type_ctor->type && "CompileTypeConstructor did not set Type");
  if (type_ctor->type->kind != Type::Kind::kIdentifier) {
    // we assume that all non-identifier types (i.e. builtins) are actually
    // types (and not e.g. protocols or services).
    return category == AllowedCategories::kProtocolOnly
               ? Fail(ErrCannotUseType, type_ctor->name.span())
               : true;
  }

  auto identifier_type = static_cast<const IdentifierType*>(type_ctor->type);
  switch (identifier_type->type_decl->kind) {
    // services are never allowed in any context
    case Decl::Kind::kService:
      return Fail(ErrCannotUseService, type_ctor->name.span());
      break;
    case Decl::Kind::kProtocol:
      if (category == AllowedCategories::kTypeOnly)
        return Fail(ErrCannotUseProtocol, type_ctor->name.span());
      break;
    default:
      if (category == AllowedCategories::kProtocolOnly)
        return Fail(ErrCannotUseType, type_ctor->name.span());
      break;
  }
  return true;
}

bool Library::ResolveHandleRightsConstant(TypeConstructor* type_ctor) {
  Decl* handle_decl = LookupDeclByName(type_ctor->name);
  if (!handle_decl || handle_decl->kind != Decl::Kind::kResource) {
    return Fail(ErrHandleSubtypeNotResource, type_ctor->name.span(), type_ctor->name);
  }

  auto* resource = static_cast<Resource*>(handle_decl);
  if (!resource->subtype_ctor || resource->subtype_ctor->name.full_name() != "uint32") {
    return Fail(ErrResourceMustBeUint32Derived, type_ctor->name.span(), resource->name);
  }

  auto rights_property = resource->LookupProperty("rights");
  if (!rights_property) {
    return Fail(ErrResourceMissingRightsProperty, type_ctor->name.span(), resource->name);
  }

  Decl* rights_decl = LookupDeclByName(rights_property->type_ctor->name);
  if (!rights_decl || rights_decl->kind != Decl::Kind::kBits) {
    return Fail(ErrResourceRightsPropertyMustReferToBits, type_ctor->name.span(), resource->name);
  }

  const Type* rights_type = rights_property->type_ctor.get()->type;
  if (!ResolveConstant(type_ctor->handle_rights.get(), rights_type)) {
    return false;
  }
  return true;
}

bool Library::ResolveHandleSubtypeIdentifier(TypeConstructor* type_ctor, uint32_t* out_obj_type,
                                             types::HandleSubtype* out_subtype) {
  assert(type_ctor->handle_subtype_identifier);

  // We only support an extremely limited form of resource suitable for
  // handles here, where it must be:
  // - derived from uint32
  // - have a single properties element
  // - the single property element must be a reference to an enum
  // - the single property must be named "subtype".

  Decl* handle_decl = LookupDeclByName(type_ctor->name);
  if (!handle_decl || handle_decl->kind != Decl::Kind::kResource) {
    return Fail(ErrHandleSubtypeNotResource, type_ctor->name.span(), type_ctor->name);
  }

  auto* resource = static_cast<Resource*>(handle_decl);
  if (!resource->subtype_ctor || resource->subtype_ctor->name.full_name() != "uint32") {
    return Fail(ErrResourceMustBeUint32Derived, type_ctor->name.span(), resource->name);
  }
  auto subtype_property = resource->LookupProperty("subtype");
  if (!subtype_property) {
    return Fail(ErrResourceMissingSubtypeProperty, type_ctor->name.span(), resource->name);
  }

  Decl* subtype_decl = LookupDeclByName(subtype_property->type_ctor->name);
  if (!subtype_decl || subtype_decl->kind != Decl::Kind::kEnum) {
    return Fail(ErrResourceSubtypePropertyMustReferToEnum, type_ctor->name.span(), resource->name);
  }

  const Type* subtype_type = subtype_property->type_ctor.get()->type;
  auto* subtype_enum = static_cast<Enum*>(subtype_decl);
  for (const auto& member : subtype_enum->members) {
    if (member.name.data() == type_ctor->handle_subtype_identifier->span()->data()) {
      if (!ResolveConstant(member.value.get(), subtype_type)) {
        return false;
      }
      const flat::ConstantValue& value = member.value->Value();
      auto obj_type = static_cast<uint32_t>(
          reinterpret_cast<const flat::NumericConstantValue<uint32_t>&>(value));
      *out_obj_type = obj_type;
      // TODO(fxbug.dev/64629): Remove.
      *out_subtype = types::HandleSubtype(obj_type);
      return true;
    }
  }

  return false;
}

bool Library::ResolveSizeBound(TypeConstructor* type_ctor, const Size** out_size) {
  if (!type_ctor->maybe_size) {
    if (out_size) {
      *out_size = nullptr;
    }
    return true;
  }

  Constant* size_constant = type_ctor->maybe_size.get();
  if (!ResolveConstant(size_constant, &kSizeType)) {
    if (size_constant->kind == Constant::Kind::kIdentifier) {
      auto name = static_cast<IdentifierConstant*>(size_constant)->name;
      if (name.library() == this && name.decl_name() == "MAX" && !name.member_name()) {
        size_constant->ResolveTo(std::make_unique<Size>(Size::Max()));
      }
    }
  }
  if (!size_constant->IsResolved()) {
    return Fail(ErrCouldNotParseSizeBound, type_ctor->name.span());
  }
  if (out_size) {
    *out_size = static_cast<const Size*>(&size_constant->Value());
  }
  return true;
}

template <typename DeclType, typename MemberType>
bool Library::ValidateMembers(DeclType* decl, MemberValidator<MemberType> validator) {
  assert(decl != nullptr);

  constexpr const char* decl_type = std::is_same_v<DeclType, Enum> ? "enum" : "bits";

  Scope<std::string> name_scope;
  Scope<MemberType> value_scope;
  bool success = true;
  for (const auto& member : decl->members) {
    assert(member.value != nullptr && "Compiler bug: member value is null!");

    if (!ResolveConstant(member.value.get(), decl->subtype_ctor->type)) {
      return Fail(ErrCouldNotResolveMember, member.name, std::string(decl_type));
    }

    // Check that the member identifier hasn't been used yet
    const auto original_name = member.name.data();
    const auto canonical_name = utils::canonicalize(original_name);
    const auto name_result = name_scope.Insert(canonical_name, member.name);
    if (!name_result.ok()) {
      const auto previous_span = name_result.previous_occurrence();
      // We can log the error and then continue validating for other issues in the decl
      if (original_name == name_result.previous_occurrence().data()) {
        success = Fail(ErrDuplicateMemberName, member.name, std::string_view(decl_type),
                       original_name, previous_span);
      } else {
        success = Fail(ErrDuplicateMemberNameCanonical, member.name, std::string_view(decl_type),
                       original_name, previous_span.data(), previous_span, canonical_name);
      }
    }

    MemberType value =
        static_cast<const NumericConstantValue<MemberType>&>(member.value->Value()).value;
    const auto value_result = value_scope.Insert(value, member.name);
    if (!value_result.ok()) {
      const auto previous_span = value_result.previous_occurrence();
      // We can log the error and then continue validating other members for other bugs
      success = Fail(ErrDuplicateMemberValue, member.name, std::string_view(decl_type),
                     original_name, previous_span.data(), previous_span);
    }

    auto err = validator(value, member.attributes.get());
    if (err) {
      err->span = member.name;
      success = Fail(std::move(err));
    }
  }

  return success;
}

template <typename T>
static bool IsPowerOfTwo(T t) {
  if (t == 0) {
    return false;
  }
  if ((t & (t - 1)) != 0) {
    return false;
  }
  return true;
}

template <typename MemberType>
bool Library::ValidateBitsMembersAndCalcMask(Bits* bits_decl, MemberType* out_mask) {
  static_assert(std::is_unsigned<MemberType>::value && !std::is_same<MemberType, bool>::value,
                "Bits members must be an unsigned integral type!");
  // Each bits member must be a power of two.
  MemberType mask = 0u;
  auto validator = [&mask](MemberType member,
                           const raw::AttributeList*) -> std::unique_ptr<Diagnostic> {
    if (!IsPowerOfTwo(member)) {
      return Reporter::MakeError(ErrBitsMemberMustBePowerOfTwo);
    }
    mask |= member;
    return nullptr;
  };
  if (!ValidateMembers<Bits, MemberType>(bits_decl, validator)) {
    return false;
  }
  *out_mask = mask;
  return true;
}

template <typename MemberType>
bool Library::ValidateEnumMembersAndCalcUnknownValue(Enum* enum_decl,
                                                     MemberType* out_unknown_value) {
  static_assert(std::is_integral<MemberType>::value && !std::is_same<MemberType, bool>::value,
                "Enum members must be an integral type!");

  auto unknown_value = std::numeric_limits<MemberType>::max();
  for (const auto& member : enum_decl->members) {
    if (!ResolveConstant(member.value.get(), enum_decl->subtype_ctor->type)) {
      return Fail(ErrCouldNotResolveMember, member.name, std::string("enum"));
    }
    auto attributes = member.attributes.get();
    if (attributes && attributes->HasAttribute("Unknown")) {
      unknown_value =
          static_cast<const NumericConstantValue<MemberType>&>(member.value->Value()).value;
    }
  }
  *out_unknown_value = unknown_value;

  auto validator = [enum_decl, unknown_value](
                       MemberType member,
                       const raw::AttributeList* attributes) -> std::unique_ptr<Diagnostic> {
    switch (enum_decl->strictness) {
      case types::Strictness::kFlexible:
        break;
      case types::Strictness::kStrict:
        // Strict enums cannot have [Unknown] attributes on members, but that will be validated by
        // ValidateUnknownConstraints() (called later in this method).
        return nullptr;
    }

    if (member != unknown_value)
      return nullptr;

    if (attributes && attributes->HasAttribute("Unknown"))
      return nullptr;

    return Reporter::MakeError(ErrFlexibleEnumMemberWithMaxValue, std::to_string(unknown_value),
                               std::to_string(unknown_value), std::to_string(unknown_value),
                               std::to_string(unknown_value));
  };

  if (!ValidateMembers<Enum, MemberType>(enum_decl, validator))
    return false;

  {
    std::vector<const Enum::Member*> members;
    members.reserve(enum_decl->members.size());
    for (const auto& member : enum_decl->members) {
      members.push_back(&member);
    }

    auto err = ValidateUnknownConstraints(*enum_decl, enum_decl->strictness, &members);
    if (err) {
      return Fail(std::move(err));
    }
  }

  return true;
}

bool Library::HasAttribute(std::string_view name) const {
  if (!attributes_)
    return false;
  return attributes_->HasAttribute(std::string(name));
}

const std::set<Library*>& Library::dependencies() const { return dependencies_.dependencies(); }

std::unique_ptr<TypeConstructor> TypeConstructor::CreateSizeType() {
  return std::make_unique<TypeConstructor>(
      Name::CreateIntrinsic("uint32"), nullptr /* maybe_arg_type */,
      std::optional<Name>() /* handle_subtype_identifier */, nullptr /* handle_rights */,
      nullptr /* maybe_size */, types::Nullability::kNonnullable, fidl::utils::Syntax::kOld);
}

}  // namespace flat
}  // namespace fidl
